From 60667c926954499f3f12848fca64e8a9c73a7308 Mon Sep 17 00:00:00 2001 From: sanny32 Date: Thu, 21 Sep 2023 08:02:43 +0300 Subject: [PATCH 01/90] Developing new log view --- omodscan/controls/outputwidget.cpp | 26 +++++++++++++++----------- omodscan/controls/outputwidget.ui | 12 +++--------- 2 files changed, 18 insertions(+), 20 deletions(-) diff --git a/omodscan/controls/outputwidget.cpp b/omodscan/controls/outputwidget.cpp index 464180d..6f67b6e 100644 --- a/omodscan/controls/outputwidget.cpp +++ b/omodscan/controls/outputwidget.cpp @@ -1085,33 +1085,37 @@ void OutputWidget::updateTrafficWidget(bool request, int server, const QModbusPd rawData.push_back(pdu.functionCode() | ( pdu.isException() ? QModbusPdu::ExceptionByte : 0)); rawData.push_back(pdu.data()); - QString text; + QStringList data; for(auto&& c : rawData) { switch(dataDisplayMode()) { case DataDisplayMode::Decimal: case DataDisplayMode::Integer: - text+= QString("[%1]").arg(QString::number((uchar)c), 3, '0'); + data+= QString("%1").arg(QString::number((uchar)c), 3, '0'); break; default: - text+= QString("[%1]").arg(QString::number((uchar)c, 16), 2, '0'); + data+= QString("%1").arg(QString::number((uchar)c, 16).toUpper(), 2, '0'); break; } } - if(text.isEmpty()) return; + if(data.isEmpty()) return; + QString text = QString("%1 %2 [%3]").arg(QDateTime::currentDateTime().toString(Qt::DateFormat::ISODateWithMs), + (request? ">>" : "<<"), + data.join(" ")); - ui->plainTextEdit->moveCursor(QTextCursor::End); + //ui->plainTextEdit->moveCursor(QTextCursor::End); QTextCharFormat fmt; - fmt.setForeground(request? foregroundColor() : Qt::white); - fmt.setBackground(request? Qt::transparent : Qt::black); + //fmt.setForeground(request? foregroundColor() : Qt::black); + //fmt.setBackground(request? Qt::transparent : Qt::white); + fmt.setFontWeight(request ? 600 : 400); ui->plainTextEdit->mergeCurrentCharFormat(fmt); - if(request && ui->plainTextEdit->toPlainText().length() > 22000) - ui->plainTextEdit->clear(); + //if(request && ui->plainTextEdit->toPlainText().length() > 22000) + // ui->plainTextEdit->clear(); - ui->plainTextEdit->insertPlainText(text); - ui->plainTextEdit->moveCursor(QTextCursor::End); + ui->plainTextEdit->appendPlainText(text); + //ui->plainTextEdit->moveCursor(QTextCursor::End); } diff --git a/omodscan/controls/outputwidget.ui b/omodscan/controls/outputwidget.ui index daa2e68..246e11f 100644 --- a/omodscan/controls/outputwidget.ui +++ b/omodscan/controls/outputwidget.ui @@ -29,7 +29,7 @@ - 0 + 1 @@ -131,23 +131,17 @@ Qt::NoFocus - - Qt::NoContextMenu - QFrame::NoFrame - - Qt::ScrollBarAlwaysOff - Qt::ScrollBarAlwaysOff - Qt::NoTextInteraction + Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse - 3 + 200 From 322d9de5e8415b9e50c3ee7431fbaa2f1e769345 Mon Sep 17 00:00:00 2001 From: sanny32 Date: Thu, 21 Sep 2023 17:12:24 +0300 Subject: [PATCH 02/90] Developing new log view --- omodscan/controls/outputwidget.cpp | 194 +++++++++++++++++++++++------ omodscan/controls/outputwidget.h | 38 ++++++ omodscan/controls/outputwidget.ui | 56 ++++++--- 3 files changed, 230 insertions(+), 58 deletions(-) diff --git a/omodscan/controls/outputwidget.cpp b/omodscan/controls/outputwidget.cpp index 6f67b6e..f844926 100644 --- a/omodscan/controls/outputwidget.cpp +++ b/omodscan/controls/outputwidget.cpp @@ -5,6 +5,7 @@ #include "floatutils.h" #include "outputwidget.h" #include "ui_outputwidget.h" +#include /// /// \brief SimulationRole @@ -575,6 +576,156 @@ QModelIndex OutputListModel::find(QModbusDataUnit::RegisterType type, quint16 ad return QModelIndex(); } +/// +/// \brief TrafficModel::TrafficModel +/// \param parent +/// +TrafficModel::TrafficModel(OutputWidget* parent) + : QAbstractListModel(parent) + ,_parentWidget(parent) +{ +} + +/// +/// \brief TrafficModel::columnCount +/// \param parent +/// \return +/// +int TrafficModel::columnCount(const QModelIndex&) const +{ + return 3; +} + +/// +/// \brief TrafficModel::rowCount +/// \param parent +/// \return +/// +int TrafficModel::rowCount(const QModelIndex&) const +{ + return _items.size(); +} + +/// +/// \brief TrafficModel::data +/// \param index +/// \param role +/// \return +/// +QVariant TrafficModel::data(const QModelIndex& index, int role) const +{ + if(!index.isValid() || index.row() >= rowCount()) + return QVariant(); + + const auto& item = _items.at(index.row()); + switch(role) + { + case Qt::DisplayRole: + { + /*switch(index.column()) + { + case 0: + return item.Date.toString(Qt::ISODateWithMs); + + case 1: + return item.Request? ">>" : "<<"; + + case 2: + { + QByteArray rawData; + rawData.push_back(item.Server); + rawData.push_back(item.Func | ( item.IsException ? QModbusPdu::ExceptionByte : 0)); + rawData.push_back(item.Data); + + QStringList data; + for(auto&& c : rawData) + { + switch(_parentWidget->dataDisplayMode()) + { + case DataDisplayMode::Decimal: + case DataDisplayMode::Integer: + data+= QString("%1").arg(QString::number((uchar)c), 3, '0'); + break; + + default: + data+= QString("%1").arg(QString::number((uchar)c, 16).toUpper(), 2, '0'); + break; + } + } + return data.join(" "); + } + + default: + break; + }*/ + + QByteArray rawData; + rawData.push_back(item.Server); + rawData.push_back(item.Func | ( item.IsException ? QModbusPdu::ExceptionByte : 0)); + rawData.push_back(item.Data); + + QStringList data; + for(auto&& c : rawData) + { + switch(_parentWidget->dataDisplayMode()) + { + case DataDisplayMode::Decimal: + case DataDisplayMode::Integer: + data+= QString("%1").arg(QString::number((uchar)c), 3, '0'); + break; + + default: + data+= QString("%1").arg(QString::number((uchar)c, 16).toUpper(), 2, '0'); + break; + } + } + return QString("%1 %2 %3").arg(item.Date.toString(Qt::ISODateWithMs), (item.Request? ">>" : "<<"), data.join(" ")); + } + break; + + /*case Qt::TextAlignmentRole: + { + switch (index.column()) + { + case 0: + case 1: + return Qt::AlignHCenter; + case 2: + return Qt::AlignLeft; + default: + break; + } + } + break;*/ + + case Qt::UserRole: + return QVariant::fromValue(item); + } + + return QVariant(); +} + +/// +/// \brief TrafficModel::clear +/// +void TrafficModel::clear() +{ + beginResetModel(); + _items.clear(); + endResetModel(); +} + +/// +/// \brief TrafficModel::append +/// \param data +/// +void TrafficModel::append(const TrafficData& data) +{ + beginInsertRows(QModelIndex(), rowCount(), rowCount()); + _items.push_back(data); + endInsertRows(); +} + /// /// \brief OutputWidget::OutputWidget /// \param parent @@ -587,10 +738,12 @@ OutputWidget::OutputWidget(QWidget *parent) : ,_dataDisplayMode(DataDisplayMode::Binary) ,_byteOrder(ByteOrder::LittleEndian) ,_listModel(new OutputListModel(this)) + ,_trafficModel(new TrafficModel(this)) { ui->setupUi(this); ui->stackedWidget->setCurrentIndex(0); ui->listView->setModel(_listModel.get()); + ui->logView->setModel(_trafficModel.get()); ui->labelStatus->setAutoFillBackground(true); setAutoFillBackground(true); @@ -1080,42 +1233,7 @@ void OutputWidget::captureString(const QString& s) /// void OutputWidget::updateTrafficWidget(bool request, int server, const QModbusPdu& pdu) { - QByteArray rawData; - rawData.push_back(server); - rawData.push_back(pdu.functionCode() | ( pdu.isException() ? QModbusPdu::ExceptionByte : 0)); - rawData.push_back(pdu.data()); - - QStringList data; - for(auto&& c : rawData) - { - switch(dataDisplayMode()) - { - case DataDisplayMode::Decimal: - case DataDisplayMode::Integer: - data+= QString("%1").arg(QString::number((uchar)c), 3, '0'); - break; - - default: - data+= QString("%1").arg(QString::number((uchar)c, 16).toUpper(), 2, '0'); - break; - } - } - if(data.isEmpty()) return; - QString text = QString("%1 %2 [%3]").arg(QDateTime::currentDateTime().toString(Qt::DateFormat::ISODateWithMs), - (request? ">>" : "<<"), - data.join(" ")); - - //ui->plainTextEdit->moveCursor(QTextCursor::End); - - QTextCharFormat fmt; - //fmt.setForeground(request? foregroundColor() : Qt::black); - //fmt.setBackground(request? Qt::transparent : Qt::white); - fmt.setFontWeight(request ? 600 : 400); - ui->plainTextEdit->mergeCurrentCharFormat(fmt); - - //if(request && ui->plainTextEdit->toPlainText().length() > 22000) - // ui->plainTextEdit->clear(); - - ui->plainTextEdit->appendPlainText(text); - //ui->plainTextEdit->moveCursor(QTextCursor::End); + _trafficModel->append({ QDateTime::currentDateTime(), request, server, pdu.isException(), pdu.functionCode(), pdu.data() }); + //ui->tableView->resizeColumnsToContents(); + ui->logView->scrollToBottom(); } diff --git a/omodscan/controls/outputwidget.h b/omodscan/controls/outputwidget.h index 904760f..17ae660 100644 --- a/omodscan/controls/outputwidget.h +++ b/omodscan/controls/outputwidget.h @@ -3,6 +3,7 @@ #include #include +#include #include #include #include "enums.h" @@ -58,6 +59,42 @@ class OutputListModel : public QAbstractListModel QMap _mapItems; }; +/// +/// \brief The TrafficData class +/// +struct TrafficData +{ + QDateTime Date; + bool Request; + int Server; + bool IsException; + QModbusPdu::FunctionCode Func; + QByteArray Data; +}; +Q_DECLARE_METATYPE(TrafficData) + +/// +/// \brief The TrafficModel class +/// +class TrafficModel : public QAbstractListModel +{ + Q_OBJECT + +public: + explicit TrafficModel(OutputWidget* parent); + + int columnCount(const QModelIndex &parent = QModelIndex()) const override; + int rowCount(const QModelIndex& parent = QModelIndex()) const override; + QVariant data(const QModelIndex& index, int role) const override; + + void clear(); + void append(const TrafficData& data); + +private: + QVector _items; + OutputWidget* _parentWidget; +}; + /// /// \brief The OutputWidget class /// @@ -143,6 +180,7 @@ private slots: QFile _fileCapture; AddressDescriptionMap _descriptionMap; QSharedPointer _listModel; + QSharedPointer _trafficModel; }; #endif // OUTPUTWIDGET_H diff --git a/omodscan/controls/outputwidget.ui b/omodscan/controls/outputwidget.ui index 246e11f..cadea55 100644 --- a/omodscan/controls/outputwidget.ui +++ b/omodscan/controls/outputwidget.ui @@ -110,10 +110,7 @@ - - - 0 - + 0 @@ -127,22 +124,41 @@ 0 - - - Qt::NoFocus - - - QFrame::NoFrame - - - Qt::ScrollBarAlwaysOff - - - Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse - - - 200 - + + + Qt::Vertical + + + + + 0 + 1 + + + + true + + + QAbstractItemView::NoEditTriggers + + + Qt::IgnoreAction + + + QAbstractItemView::SingleSelection + + + QAbstractItemView::SelectRows + + + true + + + + + QAbstractItemView::NoEditTriggers + + From 825fc84d944dc0bdbd13f5563062d6d5facb9c0f Mon Sep 17 00:00:00 2001 From: sanny32 Date: Fri, 22 Sep 2023 15:51:39 +0300 Subject: [PATCH 03/90] Developing new log view --- omodscan/controls/functioncodecombobox.cpp | 85 +--------------- omodscan/controls/outputwidget.cpp | 112 +++++++++++++++------ omodscan/controls/outputwidget.h | 9 +- omodscan/controls/outputwidget.ui | 11 +- omodscan/modbusclient.cpp | 5 +- omodscan/modbusexception.h | 7 +- omodscan/modbusfunction.h | 112 +++++++++++++++++++++ omodscan/omodscan.pro | 1 + omodscan/quintvalidator.h | 3 + 9 files changed, 228 insertions(+), 117 deletions(-) create mode 100644 omodscan/modbusfunction.h diff --git a/omodscan/controls/functioncodecombobox.cpp b/omodscan/controls/functioncodecombobox.cpp index 3bde5da..5c14b25 100644 --- a/omodscan/controls/functioncodecombobox.cpp +++ b/omodscan/controls/functioncodecombobox.cpp @@ -1,3 +1,4 @@ +#include "modbusfunction.h" #include "functioncodecombobox.h" /// @@ -35,87 +36,9 @@ void FunctionCodeComboBox::setCurrentFunctionCode(QModbusPdu::FunctionCode funcC /// void FunctionCodeComboBox::addItem(QModbusPdu::FunctionCode funcCode) { - switch(funcCode) - { - case QModbusPdu::ReadCoils: - QComboBox::addItem("01: READ COILS", QModbusPdu::ReadCoils); - break; - - case QModbusPdu::ReadDiscreteInputs: - QComboBox::addItem("02: READ INPUTS", QModbusPdu::ReadDiscreteInputs); - break; - - case QModbusPdu::ReadHoldingRegisters: - QComboBox::addItem("03: READ HOLDING REGS", QModbusPdu::ReadHoldingRegisters); - break; - - case QModbusPdu::ReadInputRegisters: - QComboBox::addItem("04: READ INPUT REGS", QModbusPdu::ReadInputRegisters); - break; - - case QModbusPdu::WriteSingleCoil: - QComboBox::addItem("05: WRITE SINGLE COIL", QModbusPdu::WriteSingleCoil); - break; - - case QModbusPdu::WriteSingleRegister: - QComboBox::addItem("06: WRITE SINGLE REG", QModbusPdu::WriteSingleRegister); - break; - - case QModbusPdu::ReadExceptionStatus: - QComboBox::addItem("07: READ EXCEPTION STAT", QModbusPdu::ReadExceptionStatus); - break; - - case QModbusPdu::Diagnostics: - QComboBox::addItem("08: DIAGNOSTICS", QModbusPdu::Diagnostics); - break; - - case QModbusPdu::GetCommEventCounter: - QComboBox::addItem("11: GET COMM EVENT CNT", QModbusPdu::GetCommEventCounter); - break; - - case QModbusPdu::GetCommEventLog: - QComboBox::addItem("12: GET COMM EVENT LOG", QModbusPdu::GetCommEventLog); - break; - - case QModbusPdu::WriteMultipleCoils: - QComboBox::addItem("15: WRITE MULT COILS", QModbusPdu::WriteMultipleCoils); - break; - - case QModbusPdu::WriteMultipleRegisters: - QComboBox::addItem("16: WRITE MULT REGS", QModbusPdu::WriteMultipleRegisters); - break; - - case QModbusPdu::ReportServerId: - QComboBox::addItem("17: REPORT SLAVE ID", QModbusPdu::ReportServerId); - break; - - case QModbusPdu::ReadFileRecord: - QComboBox::addItem("20: READ FILE RECORD", QModbusPdu::ReadFileRecord); - break; - - case QModbusPdu::WriteFileRecord: - QComboBox::addItem("21: WRITE FILE RECORD", QModbusPdu::WriteFileRecord); - break; - - case QModbusPdu::MaskWriteRegister: - QComboBox::addItem("22: MASK WRITE REG", QModbusPdu::MaskWriteRegister); - break; - - case QModbusPdu::ReadWriteMultipleRegisters: - QComboBox::addItem("23: READ WRITE MULT REGS", QModbusPdu::ReadWriteMultipleRegisters); - break; - - case QModbusPdu::ReadFifoQueue: - QComboBox::addItem("24: READ FIFO QUEUE", QModbusPdu::ReadFifoQueue); - break; - - case QModbusPdu::EncapsulatedInterfaceTransport: - QComboBox::addItem("43: ENC IFACE TRANSPORT", QModbusPdu::EncapsulatedInterfaceTransport); - break; - - default: - break; - } + ModbusFunction func(funcCode); + const auto code = QString("%1").arg(QString::number(func, 10), 2, '0'); + QComboBox::addItem(QString("%1: %2").arg(code, func), funcCode); } /// diff --git a/omodscan/controls/outputwidget.cpp b/omodscan/controls/outputwidget.cpp index f844926..fa62586 100644 --- a/omodscan/controls/outputwidget.cpp +++ b/omodscan/controls/outputwidget.cpp @@ -2,10 +2,11 @@ #include #include #include +#include "modbusfunction.h" +#include "modbusexception.h" #include "floatutils.h" #include "outputwidget.h" #include "ui_outputwidget.h" -#include /// /// \brief SimulationRole @@ -37,6 +38,25 @@ const int AddressRole = Qt::UserRole + 5; /// const int ValueRole = Qt::UserRole + 6; +/// +/// \brief formatByteValue +/// \param mode +/// \param c +/// \return +/// +QString formatByteValue(DataDisplayMode mode, char c) +{ + switch(mode) + { + case DataDisplayMode::Decimal: + case DataDisplayMode::Integer: + return QString("%1").arg(QString::number((uchar)c), 3, '0'); + + default: + return QString("%1").arg(QString::number((uchar)c, 16).toUpper(), 2, '0'); + } +} + /// /// \brief formatBinaryValue /// \param pointType @@ -639,19 +659,8 @@ QVariant TrafficModel::data(const QModelIndex& index, int role) const QStringList data; for(auto&& c : rawData) - { - switch(_parentWidget->dataDisplayMode()) - { - case DataDisplayMode::Decimal: - case DataDisplayMode::Integer: - data+= QString("%1").arg(QString::number((uchar)c), 3, '0'); - break; - - default: - data+= QString("%1").arg(QString::number((uchar)c, 16).toUpper(), 2, '0'); - break; - } - } + data += formatByteValue(_parentWidget->dataDisplayMode(), c); + return data.join(" "); } @@ -661,24 +670,13 @@ QVariant TrafficModel::data(const QModelIndex& index, int role) const QByteArray rawData; rawData.push_back(item.Server); - rawData.push_back(item.Func | ( item.IsException ? QModbusPdu::ExceptionByte : 0)); + rawData.push_back(item.FunctionCode); rawData.push_back(item.Data); QStringList data; for(auto&& c : rawData) - { - switch(_parentWidget->dataDisplayMode()) - { - case DataDisplayMode::Decimal: - case DataDisplayMode::Integer: - data+= QString("%1").arg(QString::number((uchar)c), 3, '0'); - break; + data += formatByteValue(_parentWidget->dataDisplayMode(), c); - default: - data+= QString("%1").arg(QString::number((uchar)c, 16).toUpper(), 2, '0'); - break; - } - } return QString("%1 %2 %3").arg(item.Date.toString(Qt::ISODateWithMs), (item.Request? ">>" : "<<"), data.join(" ")); } break; @@ -1203,6 +1201,55 @@ void OutputWidget::on_listView_doubleClicked(const QModelIndex& index) emit itemDoubleClicked(address, value); } +/// +/// \brief OutputWidget::on_logView_clicked +/// \param index +/// +void OutputWidget::on_logView_clicked(const QModelIndex &index) +{ + const auto data = _trafficModel->data(index, Qt::UserRole).value(); + //const auto func = ModbusFunctionCodeToString((QModbusPdu::FunctionCode)data.FunctionCode, + // dataDisplayMode() == DataDisplayMode::Hex ? 16 : 10); + + ModbusFunction func(data.FunctionCode); + + ui->listWidget->clear(); + ui->listWidget->addItem(tr("Type: %1").arg(data.Request ? tr("Tx Message") : tr("Rx Message"))); + ui->listWidget->addItem(tr("Timestamp: %1").arg(data.Date.toString(Qt::ISODateWithMs))); + ui->listWidget->addItem(tr("Device ID: %1").arg(formatByteValue(dataDisplayMode(), data.Server))); + + if(data.Request) + { + ui->listWidget->addItem(tr("Function Code: %1").arg(func)); + ui->listWidget->addItem(tr("Start Address: %1").arg((quint16)data.Data[1])); + ui->listWidget->addItem(tr("Length: %1").arg((quint16)data.Data[3])); + } + else + { + if(data.FunctionCode & QModbusPdu::ExceptionByte) + { + ModbusException ex((QModbusPdu::ExceptionCode)data.ExceptionCode); + const auto exceptionByte = (dataDisplayMode() == DataDisplayMode::Hex) ? "80" : "128"; + ui->listWidget->addItem(tr("Function Code [%1 + Rx Function Code]: %2").arg(exceptionByte, func)); + ui->listWidget->addItem(tr("Exception Code: %1").arg(ex)); + } + else + { + ui->listWidget->addItem(tr("Function Code: %1").arg(func)); + + QStringList values; + for(auto i = 1; i < data.Data.size(); i++) + values += formatByteValue(dataDisplayMode(), data.Data[i]); + + if(!values.isEmpty()) + { + ui->listWidget->addItem(tr("Bytes Count: %1").arg(data.Data.size() - 1)); + ui->listWidget->addItem(tr("Register Values: %1").arg(values.join(" "))); + } + } + } +} + /// /// \brief OutputWidget::setUninitializedStatus /// @@ -1233,7 +1280,14 @@ void OutputWidget::captureString(const QString& s) /// void OutputWidget::updateTrafficWidget(bool request, int server, const QModbusPdu& pdu) { - _trafficModel->append({ QDateTime::currentDateTime(), request, server, pdu.isException(), pdu.functionCode(), pdu.data() }); - //ui->tableView->resizeColumnsToContents(); + TrafficData data; + data.Date = QDateTime::currentDateTime(); + data.Request = request; + data.Server = server; + data.ExceptionCode = pdu.exceptionCode(); + data.FunctionCode = (pdu.isException() ? (pdu.functionCode() | QModbusPdu::ExceptionByte) : pdu.functionCode()); + data.Data = pdu.data(); + + _trafficModel->append(data); ui->logView->scrollToBottom(); } diff --git a/omodscan/controls/outputwidget.h b/omodscan/controls/outputwidget.h index 17ae660..bb35f1d 100644 --- a/omodscan/controls/outputwidget.h +++ b/omodscan/controls/outputwidget.h @@ -7,7 +7,7 @@ #include #include #include "enums.h" -#include +#include "datasimulator.h" #include "displaydefinition.h" namespace Ui { @@ -66,9 +66,9 @@ struct TrafficData { QDateTime Date; bool Request; - int Server; - bool IsException; - QModbusPdu::FunctionCode Func; + quint8 Server; + quint8 ExceptionCode; + quint8 FunctionCode; QByteArray Data; }; Q_DECLARE_METATYPE(TrafficData) @@ -162,6 +162,7 @@ class OutputWidget : public QWidget private slots: void on_listView_doubleClicked(const QModelIndex& index); void on_listView_customContextMenuRequested(const QPoint &pos); + void on_logView_clicked(const QModelIndex &index); private: void setUninitializedStatus(); diff --git a/omodscan/controls/outputwidget.ui b/omodscan/controls/outputwidget.ui index cadea55..8d2d087 100644 --- a/omodscan/controls/outputwidget.ui +++ b/omodscan/controls/outputwidget.ui @@ -132,7 +132,7 @@ 0 - 1 + 2 @@ -155,9 +155,18 @@ + + + 0 + 1 + + QAbstractItemView::NoEditTriggers + + true + diff --git a/omodscan/modbusclient.cpp b/omodscan/modbusclient.cpp index 059ceef..acbaca8 100644 --- a/omodscan/modbusclient.cpp +++ b/omodscan/modbusclient.cpp @@ -607,7 +607,10 @@ void ModbusClient::on_writeReply() auto onError = [this, reply, raw](const QString& errorDesc, int requestId) { if (reply->error() == QModbusDevice::ProtocolError) - emit modbusError(QString("%1. %2").arg(errorDesc, ModbusException(raw.exceptionCode())), requestId); + { + ModbusException ex(raw.exceptionCode()); + emit modbusError(QString("%1. %2 (0x%3)").arg(errorDesc, ex, QString::number(ex, 16)), requestId); + } else if(reply->error() != QModbusDevice::NoError) emit modbusError(QString("%1. %2").arg(errorDesc, reply->errorString()), requestId); }; diff --git a/omodscan/modbusexception.h b/omodscan/modbusexception.h index fdd59f9..f22c6ed 100644 --- a/omodscan/modbusexception.h +++ b/omodscan/modbusexception.h @@ -14,6 +14,11 @@ class ModbusException { } + operator int() + { + return _code; + } + operator QString() { QString desc; @@ -53,7 +58,7 @@ class ModbusException desc = "EXTENDED EXCEPTION"; break; } - return QString("%1 (0x%2)").arg(desc, QString::number(_code, 16)); + return desc; } private: diff --git a/omodscan/modbusfunction.h b/omodscan/modbusfunction.h new file mode 100644 index 0000000..7082d07 --- /dev/null +++ b/omodscan/modbusfunction.h @@ -0,0 +1,112 @@ +#ifndef MODBUSFUNCTION_H +#define MODBUSFUNCTION_H + +#include + +/// +/// \brief The ModbusFunction class +/// +class ModbusFunction +{ +public: + explicit ModbusFunction(QModbusPdu::FunctionCode code) + :_code(code) + { + } + + operator int() + { + return _code; + } + + operator QString() + { + QString name; + switch(_code) + { + case QModbusPdu::ReadCoils: + name = "READ COILS"; + break; + + case QModbusPdu::ReadDiscreteInputs: + name = "READ INPUTS"; + break; + + case QModbusPdu::ReadHoldingRegisters: + name = "READ HOLDING REGS"; + break; + + case QModbusPdu::ReadInputRegisters: + name = "READ INPUT REGS"; + break; + + case QModbusPdu::WriteSingleCoil: + name = "WRITE SINGLE COIL"; + break; + + case QModbusPdu::WriteSingleRegister: + name = "WRITE SINGLE REG"; + break; + + case QModbusPdu::ReadExceptionStatus: + name = "READ EXCEPTION STAT"; + break; + + case QModbusPdu::Diagnostics: + name = "DIAGNOSTICS"; + + case QModbusPdu::GetCommEventCounter: + name = "GET COMM EVENT CNT"; + break; + + case QModbusPdu::GetCommEventLog: + name = "GET COMM EVENT LOG"; + break; + + case QModbusPdu::WriteMultipleCoils: + name = "WRITE MULT COILS"; + break; + + case QModbusPdu::WriteMultipleRegisters: + name = "WRITE MULT REGS"; + break; + + case QModbusPdu::ReportServerId: + name = "REPORT SLAVE ID"; + break; + + case QModbusPdu::ReadFileRecord: + name = "READ FILE RECORD"; + break; + + case QModbusPdu::WriteFileRecord: + name = "WRITE FILE RECORD"; + break; + + case QModbusPdu::MaskWriteRegister: + name = "MASK WRITE REG"; + break; + + case QModbusPdu::ReadWriteMultipleRegisters: + name = "READ WRITE MULT REGS"; + break; + + case QModbusPdu::ReadFifoQueue: + name ="READ FIFO QUEUE"; + break; + + case QModbusPdu::EncapsulatedInterfaceTransport: + name = "ENC IFACE TRANSPORT"; + break; + + default: + break; + } + return name; + } + +private: + QModbusPdu::FunctionCode _code; +}; + +#endif // MODBUSFUNCTION_H diff --git a/omodscan/omodscan.pro b/omodscan/omodscan.pro index 7da0f51..eb7109a 100644 --- a/omodscan/omodscan.pro +++ b/omodscan/omodscan.pro @@ -126,6 +126,7 @@ HEADERS += \ modbusclient.h \ modbusdataunit.h \ modbusexception.h \ + modbusfunction.h \ modbuslimits.h \ modbusrtuscanner.h \ modbusscanner.h \ diff --git a/omodscan/quintvalidator.h b/omodscan/quintvalidator.h index 839a245..18476fc 100644 --- a/omodscan/quintvalidator.h +++ b/omodscan/quintvalidator.h @@ -4,6 +4,9 @@ #include #include +/// +/// \brief The QUIntValidator class +/// class QUIntValidator : public QValidator { Q_OBJECT From 4679897c107b849ef7694d598456b35882385e24 Mon Sep 17 00:00:00 2001 From: sanny32 Date: Mon, 25 Sep 2023 11:45:33 +0300 Subject: [PATCH 04/90] Developing new log view --- omodscan/controls/outputwidget.cpp | 133 ++++++++++++----------------- omodscan/controls/outputwidget.h | 23 ++--- omodscan/controls/outputwidget.ui | 12 +++ omodscan/modbusfunction.h | 7 +- omodscan/modbuspduinfo.h | 113 ++++++++++++++++++++++++ omodscan/omodscan.pro | 1 + 6 files changed, 193 insertions(+), 96 deletions(-) create mode 100644 omodscan/modbuspduinfo.h diff --git a/omodscan/controls/outputwidget.cpp b/omodscan/controls/outputwidget.cpp index fa62586..36bb6f0 100644 --- a/omodscan/controls/outputwidget.cpp +++ b/omodscan/controls/outputwidget.cpp @@ -38,25 +38,6 @@ const int AddressRole = Qt::UserRole + 5; /// const int ValueRole = Qt::UserRole + 6; -/// -/// \brief formatByteValue -/// \param mode -/// \param c -/// \return -/// -QString formatByteValue(DataDisplayMode mode, char c) -{ - switch(mode) - { - case DataDisplayMode::Decimal: - case DataDisplayMode::Integer: - return QString("%1").arg(QString::number((uchar)c), 3, '0'); - - default: - return QString("%1").arg(QString::number((uchar)c, 16).toUpper(), 2, '0'); - } -} - /// /// \brief formatBinaryValue /// \param pointType @@ -668,16 +649,9 @@ QVariant TrafficModel::data(const QModelIndex& index, int role) const break; }*/ - QByteArray rawData; - rawData.push_back(item.Server); - rawData.push_back(item.FunctionCode); - rawData.push_back(item.Data); - - QStringList data; - for(auto&& c : rawData) - data += formatByteValue(_parentWidget->dataDisplayMode(), c); - - return QString("%1 %2 %3").arg(item.Date.toString(Qt::ISODateWithMs), (item.Request? ">>" : "<<"), data.join(" ")); + return QString("%1 %2 %3").arg(item.timestamp().toString(Qt::ISODateWithMs), + (item.request()? ">>" : "<<"), + item.toString(_parentWidget->dataDisplayMode())); } break; @@ -717,7 +691,7 @@ void TrafficModel::clear() /// \brief TrafficModel::append /// \param data /// -void TrafficModel::append(const TrafficData& data) +void TrafficModel::append(const ModbusPduInfo& data) { beginInsertRows(QModelIndex(), rowCount(), rowCount()); _items.push_back(data); @@ -1114,6 +1088,10 @@ void OutputWidget::setDataDisplayMode(DataDisplayMode mode) { _dataDisplayMode = mode; _listModel->update(); + _trafficModel->update(); + + // update traffic info + ui->logView->clicked(ui->logView->currentIndex()); } /// @@ -1207,47 +1185,10 @@ void OutputWidget::on_listView_doubleClicked(const QModelIndex& index) /// void OutputWidget::on_logView_clicked(const QModelIndex &index) { - const auto data = _trafficModel->data(index, Qt::UserRole).value(); - //const auto func = ModbusFunctionCodeToString((QModbusPdu::FunctionCode)data.FunctionCode, - // dataDisplayMode() == DataDisplayMode::Hex ? 16 : 10); - - ModbusFunction func(data.FunctionCode); - - ui->listWidget->clear(); - ui->listWidget->addItem(tr("Type: %1").arg(data.Request ? tr("Tx Message") : tr("Rx Message"))); - ui->listWidget->addItem(tr("Timestamp: %1").arg(data.Date.toString(Qt::ISODateWithMs))); - ui->listWidget->addItem(tr("Device ID: %1").arg(formatByteValue(dataDisplayMode(), data.Server))); - - if(data.Request) - { - ui->listWidget->addItem(tr("Function Code: %1").arg(func)); - ui->listWidget->addItem(tr("Start Address: %1").arg((quint16)data.Data[1])); - ui->listWidget->addItem(tr("Length: %1").arg((quint16)data.Data[3])); - } + if(index.isValid()) + showTrafficInfo(_trafficModel->data(index, Qt::UserRole).value()); else - { - if(data.FunctionCode & QModbusPdu::ExceptionByte) - { - ModbusException ex((QModbusPdu::ExceptionCode)data.ExceptionCode); - const auto exceptionByte = (dataDisplayMode() == DataDisplayMode::Hex) ? "80" : "128"; - ui->listWidget->addItem(tr("Function Code [%1 + Rx Function Code]: %2").arg(exceptionByte, func)); - ui->listWidget->addItem(tr("Exception Code: %1").arg(ex)); - } - else - { - ui->listWidget->addItem(tr("Function Code: %1").arg(func)); - - QStringList values; - for(auto i = 1; i < data.Data.size(); i++) - values += formatByteValue(dataDisplayMode(), data.Data[i]); - - if(!values.isEmpty()) - { - ui->listWidget->addItem(tr("Bytes Count: %1").arg(data.Data.size() - 1)); - ui->listWidget->addItem(tr("Register Values: %1").arg(values.join(" "))); - } - } - } + ui->listWidget->clear(); } /// @@ -1273,6 +1214,48 @@ void OutputWidget::captureString(const QString& s) } } +/// +/// \brief OutputWidget::showTrafficInfo +/// \param data +/// +void OutputWidget::showTrafficInfo(const ModbusPduInfo& data) +{ + const auto function = QString("%1 (%2)").arg( + ModbusPduInfo::formatByteValue(dataDisplayMode(), data.function()), data.function()); + + ui->listWidget->clear(); + ui->listWidget->addItem(tr("Type: %1").arg(data.request() ? tr("Tx Message") : tr("Rx Message"))); + ui->listWidget->addItem(tr("Timestamp: %1").arg(data.timestamp().toString(Qt::ISODateWithMs))); + ui->listWidget->addItem(tr("Device ID: %1").arg(ModbusPduInfo::formatByteValue(dataDisplayMode(), data.deviceId()))); + + if(data.request()) + { + ui->listWidget->addItem(tr("Function Code: %1").arg(function)); + ui->listWidget->addItem(tr("Start Address: %1").arg(data.startAddress())); + ui->listWidget->addItem(tr("Length: %1").arg(data.length())); + } + else + { + if(data.isException()) + { + const auto exception = QString("%1 (%2)").arg(ModbusPduInfo::formatByteValue(dataDisplayMode(), data.exception()), data.exception()); + ui->listWidget->addItem(tr("Error Code: %1").arg(ModbusPduInfo::formatByteValue(dataDisplayMode(), data.function()))); + ui->listWidget->addItem(tr("Exception Code: %1").arg(exception)); + } + else + { + ui->listWidget->addItem(tr("Function Code: %1").arg(function)); + + const auto values = data.registerValues(dataDisplayMode()); + if(!values.isEmpty()) + { + ui->listWidget->addItem(tr("Bytes Count: %1").arg(ModbusPduInfo::formatByteValue(dataDisplayMode(), data.data().size() - 1))); + ui->listWidget->addItem(tr("Register Values: %1").arg(values)); + } + } + } +} + /// /// \brief OutputWidget::updateTrafficWidget /// \param request @@ -1280,14 +1263,6 @@ void OutputWidget::captureString(const QString& s) /// void OutputWidget::updateTrafficWidget(bool request, int server, const QModbusPdu& pdu) { - TrafficData data; - data.Date = QDateTime::currentDateTime(); - data.Request = request; - data.Server = server; - data.ExceptionCode = pdu.exceptionCode(); - data.FunctionCode = (pdu.isException() ? (pdu.functionCode() | QModbusPdu::ExceptionByte) : pdu.functionCode()); - data.Data = pdu.data(); - - _trafficModel->append(data); + _trafficModel->append(ModbusPduInfo(pdu, QDateTime::currentDateTime(), server, request)); ui->logView->scrollToBottom(); } diff --git a/omodscan/controls/outputwidget.h b/omodscan/controls/outputwidget.h index bb35f1d..b9bfd2e 100644 --- a/omodscan/controls/outputwidget.h +++ b/omodscan/controls/outputwidget.h @@ -7,6 +7,7 @@ #include #include #include "enums.h" +#include "modbuspduinfo.h" #include "datasimulator.h" #include "displaydefinition.h" @@ -59,20 +60,6 @@ class OutputListModel : public QAbstractListModel QMap _mapItems; }; -/// -/// \brief The TrafficData class -/// -struct TrafficData -{ - QDateTime Date; - bool Request; - quint8 Server; - quint8 ExceptionCode; - quint8 FunctionCode; - QByteArray Data; -}; -Q_DECLARE_METATYPE(TrafficData) - /// /// \brief The TrafficModel class /// @@ -88,10 +75,13 @@ class TrafficModel : public QAbstractListModel QVariant data(const QModelIndex& index, int role) const override; void clear(); - void append(const TrafficData& data); + void append(const ModbusPduInfo& data); + void update(){ + emit dataChanged(index(0), index(_items.size() - 1)); + } private: - QVector _items; + QVector _items; OutputWidget* _parentWidget; }; @@ -167,6 +157,7 @@ private slots: private: void setUninitializedStatus(); void captureString(const QString& s); + void showTrafficInfo(const ModbusPduInfo& data); void updateTrafficWidget(bool request, int server, const QModbusPdu& pdu); private: diff --git a/omodscan/controls/outputwidget.ui b/omodscan/controls/outputwidget.ui index 8d2d087..97287b1 100644 --- a/omodscan/controls/outputwidget.ui +++ b/omodscan/controls/outputwidget.ui @@ -141,6 +141,12 @@ QAbstractItemView::NoEditTriggers + + true + + + false + Qt::IgnoreAction @@ -153,6 +159,9 @@ true + + true + @@ -164,6 +173,9 @@ QAbstractItemView::NoEditTriggers + + QAbstractItemView::NoSelection + true diff --git a/omodscan/modbusfunction.h b/omodscan/modbusfunction.h index 7082d07..187c383 100644 --- a/omodscan/modbusfunction.h +++ b/omodscan/modbusfunction.h @@ -14,6 +14,11 @@ class ModbusFunction { } + bool isException() const + { + return _code & QModbusPdu::ExceptionByte; + } + operator int() { return _code; @@ -22,7 +27,7 @@ class ModbusFunction operator QString() { QString name; - switch(_code) + switch(_code & ~QModbusPdu::ExceptionByte) { case QModbusPdu::ReadCoils: name = "READ COILS"; diff --git a/omodscan/modbuspduinfo.h b/omodscan/modbuspduinfo.h new file mode 100644 index 0000000..1bc040d --- /dev/null +++ b/omodscan/modbuspduinfo.h @@ -0,0 +1,113 @@ +#ifndef MODBUSPDUINFO_H +#define MODBUSPDUINFO_H + +#include +#include +#include "enums.h" +#include "modbusfunction.h" +#include "modbusexception.h" + +/// +/// \brief The ModbusPduInfo class +/// +class ModbusPduInfo +{ +public: + explicit ModbusPduInfo() = default; + explicit ModbusPduInfo(const QModbusPdu& pdu, const QDateTime& timestamp, int deviceId, bool request){ + _timestamp = timestamp; + _deviceId = deviceId; + _request = request; + _funcCode = pdu.isException() ? (pdu.functionCode() | QModbusPdu::ExceptionByte) : pdu.functionCode(); + _exceptionCode = pdu.exceptionCode(); + _data = pdu.data(); + } + + bool isValid() const { + return !_data.isEmpty(); + } + + QDateTime timestamp() const { + return _timestamp; + } + + bool request() const { + return _request; + } + + bool deviceId() const { + return _deviceId; + } + + ModbusFunction function() const { + return ModbusFunction((QModbusPdu::FunctionCode)_funcCode); + } + + bool isException() const { + return _funcCode & QModbusPdu::ExceptionByte; + } + + ModbusException exception() const { + return ModbusException((QModbusPdu::ExceptionCode)_exceptionCode); + } + + QByteArray data() const { + return _data; + } + + quint16 startAddress() const { + if(!_request) return 0; + return _data[1]; + } + + quint16 length() const { + if(!_request) return 0; + return _data[3]; + } + + static QString formatByteValue(DataDisplayMode mode, uchar c) { + switch(mode) + { + case DataDisplayMode::Decimal: + case DataDisplayMode::Integer: + return QString("%1").arg(QString::number(c), 3, '0'); + + default: + return QString("%1").arg(QString::number(c, 16).toUpper(), 2, '0'); + } + } + + QString toString(DataDisplayMode mode) const { + QByteArray rawData; + rawData.push_back(_deviceId); + rawData.push_back(_funcCode); + rawData.push_back(_data); + + QStringList data; + for(auto&& c : rawData) + data += formatByteValue(mode, c); + + return data.join(" "); + } + + QString registerValues(DataDisplayMode mode) const { + if(_request) return QString(); + + QStringList values; + for(auto i = 1; i < _data.size(); i++) + values += ModbusPduInfo::formatByteValue(mode, _data[i]); + + return values.join(" "); + } + +private: + QDateTime _timestamp; + int _deviceId = -1; + bool _request = false; + quint8 _funcCode; + quint8 _exceptionCode; + QByteArray _data; +}; +Q_DECLARE_METATYPE(ModbusPduInfo) + +#endif // MODBUSPDUINFO_H diff --git a/omodscan/omodscan.pro b/omodscan/omodscan.pro index eb7109a..8754e90 100644 --- a/omodscan/omodscan.pro +++ b/omodscan/omodscan.pro @@ -128,6 +128,7 @@ HEADERS += \ modbusexception.h \ modbusfunction.h \ modbuslimits.h \ + modbuspduinfo.h \ modbusrtuscanner.h \ modbusscanner.h \ modbussimulationparams.h \ From 069c31bb5a9224e22deb620b1984d2af9463c156 Mon Sep 17 00:00:00 2001 From: sanny32 Date: Mon, 25 Sep 2023 12:02:13 +0300 Subject: [PATCH 05/90] Developing new log view --- omodscan/controls/outputwidget.cpp | 306 +-------------------------- omodscan/formatutils.h | 323 +++++++++++++++++++++++++++++ omodscan/modbuspduinfo.h | 79 +++++-- omodscan/omodscan.pro | 1 + 4 files changed, 394 insertions(+), 315 deletions(-) create mode 100644 omodscan/formatutils.h diff --git a/omodscan/controls/outputwidget.cpp b/omodscan/controls/outputwidget.cpp index 36bb6f0..8658bc9 100644 --- a/omodscan/controls/outputwidget.cpp +++ b/omodscan/controls/outputwidget.cpp @@ -2,9 +2,7 @@ #include #include #include -#include "modbusfunction.h" -#include "modbusexception.h" -#include "floatutils.h" +#include "formatutils.h" #include "outputwidget.h" #include "ui_outputwidget.h" @@ -38,299 +36,7 @@ const int AddressRole = Qt::UserRole + 5; /// const int ValueRole = Qt::UserRole + 6; -/// -/// \brief formatBinaryValue -/// \param pointType -/// \param value -/// \param outValue -/// \return -/// -QString formatBinaryValue(QModbusDataUnit::RegisterType pointType, quint16 value, ByteOrder order, QVariant& outValue) -{ - QString result; - value = toByteOrderValue(value, order); - - switch(pointType) - { - case QModbusDataUnit::Coils: - case QModbusDataUnit::DiscreteInputs: - result = QString("<%1>").arg(value); - break; - case QModbusDataUnit::HoldingRegisters: - case QModbusDataUnit::InputRegisters: - result = QStringLiteral("<%1>").arg(value, 16, 2, QLatin1Char('0')); - break; - default: - break; - } - outValue = value; - return result; -} - -/// -/// \brief formatDecimalValue -/// \param pointType -/// \param value -/// \param outValue -/// \return -/// -QString formatDecimalValue(QModbusDataUnit::RegisterType pointType, quint16 value, ByteOrder order, QVariant& outValue) -{ - QString result; - value = toByteOrderValue(value, order); - - switch(pointType) - { - case QModbusDataUnit::Coils: - case QModbusDataUnit::DiscreteInputs: - result = QStringLiteral("<%1>").arg(value, 1, 10, QLatin1Char('0')); - break; - case QModbusDataUnit::HoldingRegisters: - case QModbusDataUnit::InputRegisters: - result = QStringLiteral("<%1>").arg(value, 5, 10, QLatin1Char('0')); - break; - default: - break; - } - outValue = value; - return result; -} - -/// -/// \brief formatIntegerValue -/// \param pointType -/// \param value -/// \param outValue -/// \return -/// -QString formatIntegerValue(QModbusDataUnit::RegisterType pointType, qint16 value, ByteOrder order, QVariant& outValue) -{ - QString result; - value = toByteOrderValue(value, order); - - switch(pointType) - { - case QModbusDataUnit::Coils: - case QModbusDataUnit::DiscreteInputs: - result = QString("<%1>").arg(value); - break; - case QModbusDataUnit::HoldingRegisters: - case QModbusDataUnit::InputRegisters: - result = QStringLiteral("<%1>").arg(value, 5, 10, QLatin1Char(' ')); - break; - default: - break; - } - outValue = value; - return result; -} - -/// -/// \brief formatHexValue -/// \param pointType -/// \param value -/// \param outValue -/// \return -/// -QString formatHexValue(QModbusDataUnit::RegisterType pointType, quint16 value, ByteOrder order, QVariant& outValue) -{ - QString result; - value = toByteOrderValue(value, order); - - switch(pointType) - { - case QModbusDataUnit::Coils: - case QModbusDataUnit::DiscreteInputs: - result = QString("<%1>").arg(value); - break; - case QModbusDataUnit::HoldingRegisters: - case QModbusDataUnit::InputRegisters: - result = QStringLiteral("<%1H>").arg(value, 4, 16, QLatin1Char('0')); - break; - default: - break; - } - outValue = value; - return result.toUpper(); -} - -/// -/// \brief formatFloatValue -/// \param pointType -/// \param value1 -/// \param value2 -/// \param order -/// \param flag -/// \param outValue -/// \return -/// -QString formatFloatValue(QModbusDataUnit::RegisterType pointType, quint16 value1, quint16 value2, ByteOrder order, bool flag, QVariant& outValue) -{ - QString result; - switch(pointType) - { - case QModbusDataUnit::Coils: - case QModbusDataUnit::DiscreteInputs: - outValue = value1; - result = QString("<%1>").arg(value1); - break; - case QModbusDataUnit::HoldingRegisters: - case QModbusDataUnit::InputRegisters: - { - if(flag) break; - const float value = makeFloat(value1, value2, order); - outValue = value; - result = QLocale().toString(value); - } - break; - default: - break; - } - return result; -} - -/// -/// \brief formatLongValue -/// \param pointType -/// \param value1 -/// \param value2 -/// \param order -/// \param flag -/// \param outValue -/// \return -/// -QString formatLongValue(QModbusDataUnit::RegisterType pointType, quint16 value1, quint16 value2, ByteOrder order, bool flag, QVariant& outValue) -{ - QString result; - switch(pointType) - { - case QModbusDataUnit::Coils: - case QModbusDataUnit::DiscreteInputs: - outValue = value1; - result = QString("<%1>").arg(value1); - break; - case QModbusDataUnit::HoldingRegisters: - case QModbusDataUnit::InputRegisters: - { - if(flag) break; - - const qint32 value = makeLong(value1, value2, order); - outValue = value; - result = result = QString("<%1>").arg(value, 10, 10, QLatin1Char(' ')); - } - break; - default: - break; - } - return result; -} - -/// -/// \brief formatUnsignedLongValue -/// \param pointType -/// \param value1 -/// \param value2 -/// \param order -/// \param flag -/// \param outValue -/// \return -/// -QString formatUnsignedLongValue(QModbusDataUnit::RegisterType pointType, quint16 value1, quint16 value2, ByteOrder order, bool flag, QVariant& outValue) -{ - QString result; - switch(pointType) - { - case QModbusDataUnit::Coils: - case QModbusDataUnit::DiscreteInputs: - outValue = value1; - result = QString("<%1>").arg(value1); - break; - case QModbusDataUnit::HoldingRegisters: - case QModbusDataUnit::InputRegisters: - { - if(flag) break; - - const quint32 value = makeULong(value1, value2, order); - outValue = value; - result = result = QString("<%1>").arg(value, 10, 10, QLatin1Char('0')); - } - break; - default: - break; - } - return result; -} - -/// -/// \brief formatDoubleValue -/// \param pointType -/// \param value1 -/// \param value2 -/// \param value3 -/// \param value4 -/// \param order -/// \param flag -/// \param outValue -/// \return -/// -QString formatDoubleValue(QModbusDataUnit::RegisterType pointType, quint16 value1, quint16 value2, quint16 value3, quint16 value4, ByteOrder order, bool flag, QVariant& outValue) -{ - QString result; - switch(pointType) - { - case QModbusDataUnit::Coils: - case QModbusDataUnit::DiscreteInputs: - outValue = value1; - result = QString("<%1>").arg(value1); - break; - case QModbusDataUnit::HoldingRegisters: - case QModbusDataUnit::InputRegisters: - { - if(flag) break; - - const double value = makeDouble(value1, value2, value3, value4, order); - outValue = value; - result = QLocale().toString(value, 'g', 16); - } - break; - default: - break; - } - return result; -} - -/// -/// \brief formatAddress -/// \param pointType -/// \param address -/// \param hexFormat -/// \return -/// -QString formatAddress(QModbusDataUnit::RegisterType pointType, int address, bool hexFormat) -{ - QString prefix; - switch(pointType) - { - case QModbusDataUnit::Coils: - prefix = "0"; - break; - case QModbusDataUnit::DiscreteInputs: - prefix = "1"; - break; - case QModbusDataUnit::HoldingRegisters: - prefix = "4"; - break; - case QModbusDataUnit::InputRegisters: - prefix = "3"; - break; - default: - break; - } - - return hexFormat ? QStringLiteral("%1H").arg(address, 4, 16, QLatin1Char('0')) : - prefix + QStringLiteral("%1").arg(address, 4, 10, QLatin1Char('0')); -} /// /// \brief OutputListModel::OutputListModel @@ -1221,12 +927,12 @@ void OutputWidget::captureString(const QString& s) void OutputWidget::showTrafficInfo(const ModbusPduInfo& data) { const auto function = QString("%1 (%2)").arg( - ModbusPduInfo::formatByteValue(dataDisplayMode(), data.function()), data.function()); + formatByteValue(dataDisplayMode(), data.function()), data.function()); ui->listWidget->clear(); ui->listWidget->addItem(tr("Type: %1").arg(data.request() ? tr("Tx Message") : tr("Rx Message"))); ui->listWidget->addItem(tr("Timestamp: %1").arg(data.timestamp().toString(Qt::ISODateWithMs))); - ui->listWidget->addItem(tr("Device ID: %1").arg(ModbusPduInfo::formatByteValue(dataDisplayMode(), data.deviceId()))); + ui->listWidget->addItem(tr("Device ID: %1").arg(formatByteValue(dataDisplayMode(), data.deviceId()))); if(data.request()) { @@ -1238,8 +944,8 @@ void OutputWidget::showTrafficInfo(const ModbusPduInfo& data) { if(data.isException()) { - const auto exception = QString("%1 (%2)").arg(ModbusPduInfo::formatByteValue(dataDisplayMode(), data.exception()), data.exception()); - ui->listWidget->addItem(tr("Error Code: %1").arg(ModbusPduInfo::formatByteValue(dataDisplayMode(), data.function()))); + const auto exception = QString("%1 (%2)").arg(formatByteValue(dataDisplayMode(), data.exception()), data.exception()); + ui->listWidget->addItem(tr("Error Code: %1").arg(formatByteValue(dataDisplayMode(), data.function()))); ui->listWidget->addItem(tr("Exception Code: %1").arg(exception)); } else @@ -1249,7 +955,7 @@ void OutputWidget::showTrafficInfo(const ModbusPduInfo& data) const auto values = data.registerValues(dataDisplayMode()); if(!values.isEmpty()) { - ui->listWidget->addItem(tr("Bytes Count: %1").arg(ModbusPduInfo::formatByteValue(dataDisplayMode(), data.data().size() - 1))); + ui->listWidget->addItem(tr("Bytes Count: %1").arg(formatByteValue(dataDisplayMode(), data.data().size() - 1))); ui->listWidget->addItem(tr("Register Values: %1").arg(values)); } } diff --git a/omodscan/formatutils.h b/omodscan/formatutils.h new file mode 100644 index 0000000..c7bbe1d --- /dev/null +++ b/omodscan/formatutils.h @@ -0,0 +1,323 @@ +#ifndef FORMATUTILS_H +#define FORMATUTILS_H + +#include +#include +#include +#include "enums.h" +#include "floatutils.h" +#include "byteorderutils.h" + +/// +/// \brief formatByteValue +/// \param mode +/// \param c +/// \return +/// +inline QString formatByteValue(DataDisplayMode mode, uchar c) { + switch(mode) + { + case DataDisplayMode::Decimal: + case DataDisplayMode::Integer: + return QString("%1").arg(QString::number(c), 3, '0'); + + default: + return QString("%1").arg(QString::number(c, 16).toUpper(), 2, '0'); + } +} + +/// +/// \brief formatBinaryValue +/// \param pointType +/// \param value +/// \param outValue +/// \return +/// +inline QString formatBinaryValue(QModbusDataUnit::RegisterType pointType, quint16 value, ByteOrder order, QVariant& outValue) +{ + QString result; + value = toByteOrderValue(value, order); + + switch(pointType) + { + case QModbusDataUnit::Coils: + case QModbusDataUnit::DiscreteInputs: + result = QString("<%1>").arg(value); + break; + case QModbusDataUnit::HoldingRegisters: + case QModbusDataUnit::InputRegisters: + result = QStringLiteral("<%1>").arg(value, 16, 2, QLatin1Char('0')); + break; + default: + break; + } + outValue = value; + return result; +} + +/// +/// \brief formatDecimalValue +/// \param pointType +/// \param value +/// \param outValue +/// \return +/// +inline QString formatDecimalValue(QModbusDataUnit::RegisterType pointType, quint16 value, ByteOrder order, QVariant& outValue) +{ + QString result; + value = toByteOrderValue(value, order); + + switch(pointType) + { + case QModbusDataUnit::Coils: + case QModbusDataUnit::DiscreteInputs: + result = QStringLiteral("<%1>").arg(value, 1, 10, QLatin1Char('0')); + break; + case QModbusDataUnit::HoldingRegisters: + case QModbusDataUnit::InputRegisters: + result = QStringLiteral("<%1>").arg(value, 5, 10, QLatin1Char('0')); + break; + default: + break; + } + outValue = value; + return result; +} + +/// +/// \brief formatIntegerValue +/// \param pointType +/// \param value +/// \param outValue +/// \return +/// +inline QString formatIntegerValue(QModbusDataUnit::RegisterType pointType, qint16 value, ByteOrder order, QVariant& outValue) +{ + QString result; + value = toByteOrderValue(value, order); + + switch(pointType) + { + case QModbusDataUnit::Coils: + case QModbusDataUnit::DiscreteInputs: + result = QString("<%1>").arg(value); + break; + case QModbusDataUnit::HoldingRegisters: + case QModbusDataUnit::InputRegisters: + result = QStringLiteral("<%1>").arg(value, 5, 10, QLatin1Char(' ')); + break; + default: + break; + } + outValue = value; + return result; +} + +/// +/// \brief formatHexValue +/// \param pointType +/// \param value +/// \param outValue +/// \return +/// +inline QString formatHexValue(QModbusDataUnit::RegisterType pointType, quint16 value, ByteOrder order, QVariant& outValue) +{ + QString result; + value = toByteOrderValue(value, order); + + switch(pointType) + { + case QModbusDataUnit::Coils: + case QModbusDataUnit::DiscreteInputs: + result = QString("<%1>").arg(value); + break; + case QModbusDataUnit::HoldingRegisters: + case QModbusDataUnit::InputRegisters: + result = QStringLiteral("<%1H>").arg(value, 4, 16, QLatin1Char('0')); + break; + default: + break; + } + outValue = value; + return result.toUpper(); +} + +/// +/// \brief formatFloatValue +/// \param pointType +/// \param value1 +/// \param value2 +/// \param order +/// \param flag +/// \param outValue +/// \return +/// +inline QString formatFloatValue(QModbusDataUnit::RegisterType pointType, quint16 value1, quint16 value2, ByteOrder order, bool flag, QVariant& outValue) +{ + QString result; + switch(pointType) + { + case QModbusDataUnit::Coils: + case QModbusDataUnit::DiscreteInputs: + outValue = value1; + result = QString("<%1>").arg(value1); + break; + case QModbusDataUnit::HoldingRegisters: + case QModbusDataUnit::InputRegisters: + { + if(flag) break; + + const float value = makeFloat(value1, value2, order); + outValue = value; + result = QLocale().toString(value); + } + break; + default: + break; + } + return result; +} + +/// +/// \brief formatLongValue +/// \param pointType +/// \param value1 +/// \param value2 +/// \param order +/// \param flag +/// \param outValue +/// \return +/// +inline QString formatLongValue(QModbusDataUnit::RegisterType pointType, quint16 value1, quint16 value2, ByteOrder order, bool flag, QVariant& outValue) +{ + QString result; + switch(pointType) + { + case QModbusDataUnit::Coils: + case QModbusDataUnit::DiscreteInputs: + outValue = value1; + result = QString("<%1>").arg(value1); + break; + case QModbusDataUnit::HoldingRegisters: + case QModbusDataUnit::InputRegisters: + { + if(flag) break; + + const qint32 value = makeLong(value1, value2, order); + outValue = value; + result = result = QString("<%1>").arg(value, 10, 10, QLatin1Char(' ')); + } + break; + default: + break; + } + return result; +} + +/// +/// \brief formatUnsignedLongValue +/// \param pointType +/// \param value1 +/// \param value2 +/// \param order +/// \param flag +/// \param outValue +/// \return +/// +inline QString formatUnsignedLongValue(QModbusDataUnit::RegisterType pointType, quint16 value1, quint16 value2, ByteOrder order, bool flag, QVariant& outValue) +{ + QString result; + switch(pointType) + { + case QModbusDataUnit::Coils: + case QModbusDataUnit::DiscreteInputs: + outValue = value1; + result = QString("<%1>").arg(value1); + break; + case QModbusDataUnit::HoldingRegisters: + case QModbusDataUnit::InputRegisters: + { + if(flag) break; + + const quint32 value = makeULong(value1, value2, order); + outValue = value; + result = result = QString("<%1>").arg(value, 10, 10, QLatin1Char('0')); + } + break; + default: + break; + } + return result; +} + +/// +/// \brief formatDoubleValue +/// \param pointType +/// \param value1 +/// \param value2 +/// \param value3 +/// \param value4 +/// \param order +/// \param flag +/// \param outValue +/// \return +/// +inline QString formatDoubleValue(QModbusDataUnit::RegisterType pointType, quint16 value1, quint16 value2, quint16 value3, quint16 value4, ByteOrder order, bool flag, QVariant& outValue) +{ + QString result; + switch(pointType) + { + case QModbusDataUnit::Coils: + case QModbusDataUnit::DiscreteInputs: + outValue = value1; + result = QString("<%1>").arg(value1); + break; + case QModbusDataUnit::HoldingRegisters: + case QModbusDataUnit::InputRegisters: + { + if(flag) break; + + const double value = makeDouble(value1, value2, value3, value4, order); + outValue = value; + result = QLocale().toString(value, 'g', 16); + } + break; + default: + break; + } + return result; +} + +/// +/// \brief formatAddress +/// \param pointType +/// \param address +/// \param hexFormat +/// \return +/// +inline QString formatAddress(QModbusDataUnit::RegisterType pointType, int address, bool hexFormat) +{ + QString prefix; + switch(pointType) + { + case QModbusDataUnit::Coils: + prefix = "0"; + break; + case QModbusDataUnit::DiscreteInputs: + prefix = "1"; + break; + case QModbusDataUnit::HoldingRegisters: + prefix = "4"; + break; + case QModbusDataUnit::InputRegisters: + prefix = "3"; + break; + default: + break; + } + + return hexFormat ? QStringLiteral("%1H").arg(address, 4, 16, QLatin1Char('0')) : + prefix + QStringLiteral("%1").arg(address, 4, 10, QLatin1Char('0')); +} + +#endif // FORMATUTILS_H diff --git a/omodscan/modbuspduinfo.h b/omodscan/modbuspduinfo.h index 1bc040d..5e9e308 100644 --- a/omodscan/modbuspduinfo.h +++ b/omodscan/modbuspduinfo.h @@ -3,7 +3,7 @@ #include #include -#include "enums.h" +#include "formatutils.h" #include "modbusfunction.h" #include "modbusexception.h" @@ -13,7 +13,18 @@ class ModbusPduInfo { public: + /// + /// \brief ModbusPduInfo + /// explicit ModbusPduInfo() = default; + + /// + /// \brief ModbusPduInfo + /// \param pdu + /// \param timestamp + /// \param deviceId + /// \param request + /// explicit ModbusPduInfo(const QModbusPdu& pdu, const QDateTime& timestamp, int deviceId, bool request){ _timestamp = timestamp; _deviceId = deviceId; @@ -23,60 +34,93 @@ class ModbusPduInfo _data = pdu.data(); } + /// + /// \brief isValid + /// \return + /// bool isValid() const { - return !_data.isEmpty(); + return _deviceId >= 0 && !_data.isEmpty(); } + /// + /// \brief timestamp + /// \return + /// QDateTime timestamp() const { return _timestamp; } + /// + /// \brief request + /// \return + /// bool request() const { return _request; } + /// + /// \brief deviceId + /// \return + /// bool deviceId() const { return _deviceId; } + /// + /// \brief function + /// \return + /// ModbusFunction function() const { return ModbusFunction((QModbusPdu::FunctionCode)_funcCode); } + /// + /// \brief isException + /// \return + /// bool isException() const { return _funcCode & QModbusPdu::ExceptionByte; } + /// + /// \brief exception + /// \return + /// ModbusException exception() const { return ModbusException((QModbusPdu::ExceptionCode)_exceptionCode); } + /// + /// \brief data + /// \return + /// QByteArray data() const { return _data; } + /// + /// \brief startAddress + /// \return + /// quint16 startAddress() const { if(!_request) return 0; return _data[1]; } + /// + /// \brief length + /// \return + /// quint16 length() const { if(!_request) return 0; return _data[3]; } - static QString formatByteValue(DataDisplayMode mode, uchar c) { - switch(mode) - { - case DataDisplayMode::Decimal: - case DataDisplayMode::Integer: - return QString("%1").arg(QString::number(c), 3, '0'); - - default: - return QString("%1").arg(QString::number(c, 16).toUpper(), 2, '0'); - } - } - + /// + /// \brief toString + /// \param mode + /// \return + /// QString toString(DataDisplayMode mode) const { QByteArray rawData; rawData.push_back(_deviceId); @@ -90,12 +134,17 @@ class ModbusPduInfo return data.join(" "); } + /// + /// \brief registerValues + /// \param mode + /// \return + /// QString registerValues(DataDisplayMode mode) const { if(_request) return QString(); QStringList values; for(auto i = 1; i < _data.size(); i++) - values += ModbusPduInfo::formatByteValue(mode, _data[i]); + values += formatByteValue(mode, _data[i]); return values.join(" "); } diff --git a/omodscan/omodscan.pro b/omodscan/omodscan.pro index 8754e90..c11d324 100644 --- a/omodscan/omodscan.pro +++ b/omodscan/omodscan.pro @@ -121,6 +121,7 @@ HEADERS += \ displaydefinition.h \ enums.h \ floatutils.h \ + formatutils.h \ formmodsca.h \ mainwindow.h \ modbusclient.h \ From 14d91e27da990852ee123a3d94260446b662e483 Mon Sep 17 00:00:00 2001 From: sanny32 Date: Tue, 26 Sep 2023 17:10:50 +0300 Subject: [PATCH 06/90] Developing new log view --- omodscan/controls/outputwidget.cpp | 181 +++++++++--------- omodscan/controls/outputwidget.h | 7 +- omodscan/controls/outputwidget.ui | 2 +- .../dialogs/dialogforcemultipleregisters.cpp | 2 +- omodscan/formatutils.h | 17 +- omodscan/htmldelegate.cpp | 88 +++++++++ omodscan/htmldelegate.h | 23 +++ omodscan/modbusclient.cpp | 2 +- omodscan/modbusinfo/modbuspduinfo.cpp | 23 +++ omodscan/{ => modbusinfo}/modbuspduinfo.h | 63 +++--- omodscan/modbusinfo/readcoils.h | 89 +++++++++ omodscan/{floatutils.h => numericutils.h} | 25 ++- omodscan/omodscan.pro | 9 +- 13 files changed, 396 insertions(+), 135 deletions(-) create mode 100644 omodscan/htmldelegate.cpp create mode 100644 omodscan/htmldelegate.h create mode 100644 omodscan/modbusinfo/modbuspduinfo.cpp rename omodscan/{ => modbusinfo}/modbuspduinfo.h (84%) create mode 100644 omodscan/modbusinfo/readcoils.h rename omodscan/{floatutils.h => numericutils.h} (88%) diff --git a/omodscan/controls/outputwidget.cpp b/omodscan/controls/outputwidget.cpp index 8658bc9..e87f935 100644 --- a/omodscan/controls/outputwidget.cpp +++ b/omodscan/controls/outputwidget.cpp @@ -3,7 +3,9 @@ #include #include #include "formatutils.h" +#include "htmldelegate.h" #include "outputwidget.h" +#include "readcoils.h" #include "ui_outputwidget.h" /// @@ -37,7 +39,6 @@ const int AddressRole = Qt::UserRole + 5; const int ValueRole = Qt::UserRole + 6; - /// /// \brief OutputListModel::OutputListModel /// \param parent @@ -328,53 +329,10 @@ QVariant TrafficModel::data(const QModelIndex& index, int role) const switch(role) { case Qt::DisplayRole: - { - /*switch(index.column()) - { - case 0: - return item.Date.toString(Qt::ISODateWithMs); - - case 1: - return item.Request? ">>" : "<<"; + return QString("%1 %2 %3").arg(item->timestamp().toString(Qt::ISODateWithMs), + (item->request()? "→" : "←"), + item->toString(_parentWidget->dataDisplayMode())); - case 2: - { - QByteArray rawData; - rawData.push_back(item.Server); - rawData.push_back(item.Func | ( item.IsException ? QModbusPdu::ExceptionByte : 0)); - rawData.push_back(item.Data); - - QStringList data; - for(auto&& c : rawData) - data += formatByteValue(_parentWidget->dataDisplayMode(), c); - - return data.join(" "); - } - - default: - break; - }*/ - - return QString("%1 %2 %3").arg(item.timestamp().toString(Qt::ISODateWithMs), - (item.request()? ">>" : "<<"), - item.toString(_parentWidget->dataDisplayMode())); - } - break; - - /*case Qt::TextAlignmentRole: - { - switch (index.column()) - { - case 0: - case 1: - return Qt::AlignHCenter; - case 2: - return Qt::AlignLeft; - default: - break; - } - } - break;*/ case Qt::UserRole: return QVariant::fromValue(item); @@ -397,8 +355,10 @@ void TrafficModel::clear() /// \brief TrafficModel::append /// \param data /// -void TrafficModel::append(const ModbusPduInfo& data) +void TrafficModel::append(const ModbusPduInfo* data) { + if(data == nullptr) return; + beginInsertRows(QModelIndex(), rowCount(), rowCount()); _items.push_back(data); endInsertRows(); @@ -430,6 +390,24 @@ OutputWidget::OutputWidget(QWidget *parent) : setStatusColor(Qt::red); setUninitializedStatus(); + + ui->logView->setItemDelegate(new HtmlDelegate(this)); + ui->trafficInfo->setItemDelegate(new HtmlDelegate(this)); + + connect(ui->logView->selectionModel(), + &QItemSelectionModel::selectionChanged, + this, [&](const QItemSelection& sel) { + if(sel.indexes().isEmpty()) + ui->trafficInfo->clear(); + else + showTrafficInfo(_trafficModel->data(sel.indexes().first(), Qt::UserRole).value()); + }); + + connect(_trafficModel.get(), &TrafficModel::rowsInserted, + this, [&](const QModelIndex&, int first, int last) { + const auto index = _trafficModel->index(first); + ui->logView->scrollTo(index); + }); } /// @@ -610,6 +588,8 @@ void OutputWidget::setFont(const QFont& font) { ui->listView->setFont(font); ui->labelStatus->setFont(font); + ui->logView->setFont(font); + ui->trafficInfo->setFont(font); } /// @@ -885,17 +865,6 @@ void OutputWidget::on_listView_doubleClicked(const QModelIndex& index) emit itemDoubleClicked(address, value); } -/// -/// \brief OutputWidget::on_logView_clicked -/// \param index -/// -void OutputWidget::on_logView_clicked(const QModelIndex &index) -{ - if(index.isValid()) - showTrafficInfo(_trafficModel->data(index, Qt::UserRole).value()); - else - ui->listWidget->clear(); -} /// /// \brief OutputWidget::setUninitializedStatus @@ -924,41 +893,75 @@ void OutputWidget::captureString(const QString& s) /// \brief OutputWidget::showTrafficInfo /// \param data /// -void OutputWidget::showTrafficInfo(const ModbusPduInfo& data) +void OutputWidget::showTrafficInfo(const ModbusPduInfo* data) { const auto function = QString("%1 (%2)").arg( - formatByteValue(dataDisplayMode(), data.function()), data.function()); + formatByteValue(dataDisplayMode(), data->function()), data->function()); - ui->listWidget->clear(); - ui->listWidget->addItem(tr("Type: %1").arg(data.request() ? tr("Tx Message") : tr("Rx Message"))); - ui->listWidget->addItem(tr("Timestamp: %1").arg(data.timestamp().toString(Qt::ISODateWithMs))); - ui->listWidget->addItem(tr("Device ID: %1").arg(formatByteValue(dataDisplayMode(), data.deviceId()))); - - if(data.request()) + auto fnPrintException = [&]() { - ui->listWidget->addItem(tr("Function Code: %1").arg(function)); - ui->listWidget->addItem(tr("Start Address: %1").arg(data.startAddress())); - ui->listWidget->addItem(tr("Length: %1").arg(data.length())); - } - else + const auto exception = QString("%1 (%2)").arg(formatByteValue(dataDisplayMode(), data->exception()), data->exception()); + ui->trafficInfo->addItem(tr("Error Code: %1").arg(formatByteValue(dataDisplayMode(), data->function()))); + ui->trafficInfo->addItem(tr("Exception Code: %1").arg(exception)); + }; + + ui->trafficInfo->clear(); + ui->trafficInfo->addItem(tr("Type: %1").arg(data->request() ? tr("Tx Message") : tr("Rx Message"))); + ui->trafficInfo->addItem(tr("Timestamp: %1").arg(data->timestamp().toString(Qt::ISODateWithMs))); + ui->trafficInfo->addItem(tr("Device ID: %1").arg(formatByteValue(dataDisplayMode(), data->deviceId()))); + + switch(data->function()) { - if(data.isException()) - { - const auto exception = QString("%1 (%2)").arg(formatByteValue(dataDisplayMode(), data.exception()), data.exception()); - ui->listWidget->addItem(tr("Error Code: %1").arg(formatByteValue(dataDisplayMode(), data.function()))); - ui->listWidget->addItem(tr("Exception Code: %1").arg(exception)); - } - else - { - ui->listWidget->addItem(tr("Function Code: %1").arg(function)); - - const auto values = data.registerValues(dataDisplayMode()); - if(!values.isEmpty()) + case QModbusPdu::ReadCoils: + { + if(data->request()) + { + auto req = qobject_cast(data); + ui->trafficInfo->addItem(tr("Function Code: %1").arg(function)); + ui->trafficInfo->addItem(tr("Start Address: %1").arg(req->startAddress())); + ui->trafficInfo->addItem(tr("Length: %1").arg(req->length())); + } + else if(data->isException()) + { + fnPrintException(); + } + else { - ui->listWidget->addItem(tr("Bytes Count: %1").arg(formatByteValue(dataDisplayMode(), data.data().size() - 1))); - ui->listWidget->addItem(tr("Register Values: %1").arg(values)); + auto resp = qobject_cast(data); + ui->trafficInfo->addItem(tr("Function Code: %1").arg(function)); + ui->trafficInfo->addItem(tr("Byte Count: %1").arg(formatByteValue(dataDisplayMode(), resp->bytesCount()))); + ui->trafficInfo->addItem(tr("Coil Status: %1").arg(formatByteArray(dataDisplayMode(), resp->coilsStatus()))); } - } + } + break; + + /*case QModbusPdu::ReadDiscreteInputs: + case QModbusPdu::ReadHoldingRegisters: + case QModbusPdu::ReadInputRegisters: + break; + + case QModbusPdu::WriteSingleCoil: + ui->trafficInfo->addItem(tr("Output Address: %1").arg(data.startAddress())); + ui->trafficInfo->addItem(tr("Output Value: %1").arg(data.length())); + break; + + case QModbusPdu::WriteSingleRegister: + ui->trafficInfo->addItem(tr("Register Address: %1").arg(data.startAddress())); + ui->trafficInfo->addItem(tr("Register Value: %1").arg(data.length())); + break; + + case QModbusPdu::WriteMultipleCoils: + ui->trafficInfo->addItem(tr("Starting Address: %1").arg(data.startAddress())); + ui->trafficInfo->addItem(tr("Quantity of Outputs: %1").arg(data.length())); + ui->trafficInfo->addItem(tr("Byte Count: %1").arg(data.length())); + ui->trafficInfo->addItem(tr("Output Value: %1").arg(data.length())); + break; + case QModbusPdu::WriteMultipleRegisters: + ui->trafficInfo->addItem(tr("Starting Address: %1").arg(data.startAddress())); + ui->trafficInfo->addItem(tr("Quantity of Registers: %1").arg(data.length())); + ui->trafficInfo->addItem(tr("Byte Count: %1").arg(data.length())); + ui->trafficInfo->addItem(tr("Registers Value: %1").arg(data.length())); + break;*/ } } @@ -969,6 +972,6 @@ void OutputWidget::showTrafficInfo(const ModbusPduInfo& data) /// void OutputWidget::updateTrafficWidget(bool request, int server, const QModbusPdu& pdu) { - _trafficModel->append(ModbusPduInfo(pdu, QDateTime::currentDateTime(), server, request)); - ui->logView->scrollToBottom(); + auto info = ModbusPduInfo::create(pdu, QDateTime::currentDateTime(), server, request, this); + _trafficModel->append(info); } diff --git a/omodscan/controls/outputwidget.h b/omodscan/controls/outputwidget.h index b9bfd2e..03f7863 100644 --- a/omodscan/controls/outputwidget.h +++ b/omodscan/controls/outputwidget.h @@ -75,14 +75,14 @@ class TrafficModel : public QAbstractListModel QVariant data(const QModelIndex& index, int role) const override; void clear(); - void append(const ModbusPduInfo& data); + void append(const ModbusPduInfo* data); void update(){ emit dataChanged(index(0), index(_items.size() - 1)); } private: - QVector _items; OutputWidget* _parentWidget; + QVector _items; }; /// @@ -152,12 +152,11 @@ class OutputWidget : public QWidget private slots: void on_listView_doubleClicked(const QModelIndex& index); void on_listView_customContextMenuRequested(const QPoint &pos); - void on_logView_clicked(const QModelIndex &index); private: void setUninitializedStatus(); void captureString(const QString& s); - void showTrafficInfo(const ModbusPduInfo& data); + void showTrafficInfo(const ModbusPduInfo* data); void updateTrafficWidget(bool request, int server, const QModbusPdu& pdu); private: diff --git a/omodscan/controls/outputwidget.ui b/omodscan/controls/outputwidget.ui index 97287b1..a8ea2a1 100644 --- a/omodscan/controls/outputwidget.ui +++ b/omodscan/controls/outputwidget.ui @@ -163,7 +163,7 @@ true - + 0 diff --git a/omodscan/dialogs/dialogforcemultipleregisters.cpp b/omodscan/dialogs/dialogforcemultipleregisters.cpp index a284d99..ef9f71e 100644 --- a/omodscan/dialogs/dialogforcemultipleregisters.cpp +++ b/omodscan/dialogs/dialogforcemultipleregisters.cpp @@ -1,6 +1,6 @@ #include #include -#include "floatutils.h" +#include "numericutils.h" #include "numericlineedit.h" #include "dialogforcemultipleregisters.h" #include "ui_dialogforcemultipleregisters.h" diff --git a/omodscan/formatutils.h b/omodscan/formatutils.h index c7bbe1d..d7ad89e 100644 --- a/omodscan/formatutils.h +++ b/omodscan/formatutils.h @@ -5,7 +5,7 @@ #include #include #include "enums.h" -#include "floatutils.h" +#include "numericutils.h" #include "byteorderutils.h" /// @@ -26,6 +26,21 @@ inline QString formatByteValue(DataDisplayMode mode, uchar c) { } } +/// +/// \brief formatByteArray +/// \param mode +/// \param ar +/// \return +/// +inline QString formatByteArray(DataDisplayMode mode, const QByteArray& ar) +{ + QStringList values; + for(auto i = 0; i < ar.size(); i++) + values += formatByteValue(mode, ar[i]); + + return values.join(" "); +} + /// /// \brief formatBinaryValue /// \param pointType diff --git a/omodscan/htmldelegate.cpp b/omodscan/htmldelegate.cpp new file mode 100644 index 0000000..f0a9f92 --- /dev/null +++ b/omodscan/htmldelegate.cpp @@ -0,0 +1,88 @@ +#include +#include +#include +#include +#include +#include "htmldelegate.h" + +/// +/// \brief HtmlDelegate::HtmlDelegate +/// \param parent +/// +HtmlDelegate::HtmlDelegate(QObject* parent) + :QStyledItemDelegate(parent) +{ +} + +/// +/// \brief HtmlDelegate::paint +/// \param painter +/// \param option +/// \param index +/// +void HtmlDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const +{ + QStyleOptionViewItem opt = option; + initStyleOption(&opt, index); + + if (opt.text.isEmpty()) { + // This is nothing this function is supposed to handle + QStyledItemDelegate::paint(painter, option, index); + + return; + } + + QStyle *style = opt.widget? opt.widget->style() : QApplication::style(); + + QTextOption textOption; + textOption.setWrapMode(opt.features & QStyleOptionViewItem::WrapText ? QTextOption::WordWrap + : QTextOption::ManualWrap); + textOption.setTextDirection(opt.direction); + + QTextDocument doc; + doc.setHtml(opt.text); + doc.setDefaultFont(opt.font); + doc.setDefaultTextOption(textOption); + doc.setTextWidth(opt.rect.width()); + + /// Painting item without text + opt.text = QString(); + style->drawControl(QStyle::CE_ItemViewItem, &opt, painter); + + QAbstractTextDocumentLayout::PaintContext ctx; + + // Highlighting text if item is selected + if (opt.state & QStyle::State_Selected) + ctx.palette.setColor(QPalette::Text, opt.palette.color(QPalette::Active, QPalette::HighlightedText)); + + QRect textRect = style->subElementRect(QStyle::SE_ItemViewItemText, &opt); + painter->save(); + painter->translate(textRect.topLeft()); + painter->setClipRect(textRect.translated(-textRect.topLeft())); + doc.documentLayout()->draw(painter, ctx); + painter->restore(); +} + +/// +/// \brief HtmlDelegate::sizeHint +/// \param option +/// \param index +/// \return +/// +QSize HtmlDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const +{ + QStyleOptionViewItem opt = option; + initStyleOption(&opt, index); + + if (opt.text.isEmpty()) { + // This is nothing this function is supposed to handle + return QStyledItemDelegate::sizeHint(option, index); + } + + QTextDocument doc; + doc.setHtml(opt.text); + doc.setDefaultFont(opt.font); + doc.setTextWidth(opt.rect.width()); + + return QSize(doc.idealWidth(), doc.size().height()); +} diff --git a/omodscan/htmldelegate.h b/omodscan/htmldelegate.h new file mode 100644 index 0000000..8f6269e --- /dev/null +++ b/omodscan/htmldelegate.h @@ -0,0 +1,23 @@ +#ifndef HTMLDELEGATE_H +#define HTMLDELEGATE_H + +#include + +/// +/// \brief The HtmlDelegate class +/// +class HtmlDelegate : public QStyledItemDelegate +{ +public: + /// + /// \brief HtmlDelegate + /// \param parent + /// + explicit HtmlDelegate(QObject* parent = nullptr); + +protected: + void paint ( QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index ) const; + QSize sizeHint ( const QStyleOptionViewItem & option, const QModelIndex & index ) const; +}; + +#endif // HTMLDELEGATE_H diff --git a/omodscan/modbusclient.cpp b/omodscan/modbusclient.cpp index acbaca8..f5470ef 100644 --- a/omodscan/modbusclient.cpp +++ b/omodscan/modbusclient.cpp @@ -1,5 +1,5 @@ #include -#include "floatutils.h" +#include "numericutils.h" #include "modbusexception.h" #include "modbusclient.h" diff --git a/omodscan/modbusinfo/modbuspduinfo.cpp b/omodscan/modbusinfo/modbuspduinfo.cpp new file mode 100644 index 0000000..dd94abf --- /dev/null +++ b/omodscan/modbusinfo/modbuspduinfo.cpp @@ -0,0 +1,23 @@ +#include "modbuspduinfo.h" +#include "readcoils.h" + +/// +/// \brief ModbusPduInfo::create +/// \param pdu +/// \param timestamp +/// \param deviceId +/// \param request +/// \return +/// +const ModbusPduInfo* ModbusPduInfo::create(const QModbusPdu& pdu, const QDateTime& timestamp, int deviceId, bool request, QObject* parent) +{ + switch(pdu.functionCode()) + { + case QModbusPdu::ReadCoils: + if(request) return new ReadCoilsRequest(pdu, timestamp, deviceId, parent); + else return new ReadCoilsResponse(pdu, timestamp, deviceId, parent); + + default: + return nullptr; + } +} diff --git a/omodscan/modbuspduinfo.h b/omodscan/modbusinfo/modbuspduinfo.h similarity index 84% rename from omodscan/modbuspduinfo.h rename to omodscan/modbusinfo/modbuspduinfo.h index 5e9e308..f94d863 100644 --- a/omodscan/modbuspduinfo.h +++ b/omodscan/modbusinfo/modbuspduinfo.h @@ -10,8 +10,9 @@ /// /// \brief The ModbusPduInfo class /// -class ModbusPduInfo +class ModbusPduInfo: public QObject { + Q_OBJECT public: /// /// \brief ModbusPduInfo @@ -19,26 +20,20 @@ class ModbusPduInfo explicit ModbusPduInfo() = default; /// - /// \brief ModbusPduInfo + /// \brief create /// \param pdu /// \param timestamp /// \param deviceId /// \param request + /// \return /// - explicit ModbusPduInfo(const QModbusPdu& pdu, const QDateTime& timestamp, int deviceId, bool request){ - _timestamp = timestamp; - _deviceId = deviceId; - _request = request; - _funcCode = pdu.isException() ? (pdu.functionCode() | QModbusPdu::ExceptionByte) : pdu.functionCode(); - _exceptionCode = pdu.exceptionCode(); - _data = pdu.data(); - } + static const ModbusPduInfo* create(const QModbusPdu& pdu, const QDateTime& timestamp, int deviceId, bool request, QObject* parent = nullptr); /// /// \brief isValid /// \return /// - bool isValid() const { + virtual bool isValid() const { return _deviceId >= 0 && !_data.isEmpty(); } @@ -98,24 +93,6 @@ class ModbusPduInfo return _data; } - /// - /// \brief startAddress - /// \return - /// - quint16 startAddress() const { - if(!_request) return 0; - return _data[1]; - } - - /// - /// \brief length - /// \return - /// - quint16 length() const { - if(!_request) return 0; - return _data[3]; - } - /// /// \brief toString /// \param mode @@ -149,14 +126,34 @@ class ModbusPduInfo return values.join(" "); } +protected: + /// + /// \brief ModbusPduInfo + /// \param pdu + /// \param timestamp + /// \param deviceId + /// \param request + /// + ModbusPduInfo(const QModbusPdu& pdu, const QDateTime& timestamp, int deviceId, bool request, QObject* parent = nullptr) + : QObject(parent) + { + _timestamp = timestamp; + _deviceId = deviceId; + _request = request; + _funcCode = pdu.isException() ? (pdu.functionCode() | QModbusPdu::ExceptionByte) : pdu.functionCode(); + _exceptionCode = pdu.exceptionCode(); + _data = pdu.data(); + } + +protected: + QByteArray _data; + quint8 _funcCode; + quint8 _exceptionCode; + private: QDateTime _timestamp; int _deviceId = -1; bool _request = false; - quint8 _funcCode; - quint8 _exceptionCode; - QByteArray _data; }; -Q_DECLARE_METATYPE(ModbusPduInfo) #endif // MODBUSPDUINFO_H diff --git a/omodscan/modbusinfo/readcoils.h b/omodscan/modbusinfo/readcoils.h new file mode 100644 index 0000000..3e3547a --- /dev/null +++ b/omodscan/modbusinfo/readcoils.h @@ -0,0 +1,89 @@ +#ifndef READCOILS_H +#define READCOILS_H + +#include "numericutils.h" +#include "modbuspduinfo.h" + +/// +/// \brief The ReadCoilsRequest class +/// +class ReadCoilsRequest : public ModbusPduInfo +{ + Q_OBJECT +public: + /// + /// \brief ReadCoilsRequest + /// + explicit ReadCoilsRequest() = default; + + /// + /// \brief ReadCoilsRequest + /// \param pdu + /// \param timestamp + /// \param deviceId + /// + ReadCoilsRequest(const QModbusPdu& pdu, const QDateTime& timestamp, int deviceId, QObject* parent) + : ModbusPduInfo(pdu, timestamp, deviceId, true, parent) + { + Q_ASSERT(_funcCode == QModbusPdu::ReadCoils); + } + + /// + /// \brief startAddress + /// \return + /// + quint16 startAddress() const { + return makeWord(_data[1], _data[2], ByteOrder::LittleEndian); + } + + /// + /// \brief length + /// \return + /// + quint16 length() const { + return makeWord(_data[3], _data[4], ByteOrder::LittleEndian); + } +}; + +/// +/// \brief The ReadCoilsResponse class +/// +class ReadCoilsResponse : public ModbusPduInfo +{ + Q_OBJECT +public: + /// + /// \brief ReadCoilsResponse + /// + explicit ReadCoilsResponse() = default; + + /// + /// \brief ReadCoilsResponse + /// \param pdu + /// \param timestamp + /// \param deviceId + /// + ReadCoilsResponse(const QModbusPdu& pdu, const QDateTime& timestamp, int deviceId, QObject* parent) + :ModbusPduInfo(pdu, timestamp, deviceId, false, parent) + { + Q_ASSERT(_funcCode == QModbusPdu::ReadCoils); + } + + /// + /// \brief bytesCount + /// \return + /// + quint8 bytesCount() const { + return _data[1]; + } + + /// + /// \brief coilsStatus + /// \return + /// + QByteArray coilsStatus() const { + return QByteArray(_data + 2, _data.size() - 2); + } +}; + +#endif // READCOILS_H diff --git a/omodscan/floatutils.h b/omodscan/numericutils.h similarity index 88% rename from omodscan/floatutils.h rename to omodscan/numericutils.h index c0d89cd..06c9902 100644 --- a/omodscan/floatutils.h +++ b/omodscan/numericutils.h @@ -1,10 +1,29 @@ -#ifndef FLOATUTILS_H -#define FLOATUTILS_H +#ifndef NUMERICUTILS_H +#define NUMERICUTILS_H #include #include #include "byteorderutils.h" +/// +/// \brief makeWord +/// \param lo +/// \param hi +/// \return +/// +inline quint16 makeWord(quint8 lo, quint8 hi, ByteOrder order) +{ + union { + quint8 asUint8[2]; + quint16 asUint16; + } v; + + v.asUint8[0] = toByteOrderValue(lo, order); + v.asUint8[1] = toByteOrderValue(hi, order); + + return v.asUint16; +} + /// /// \brief breakFloat /// \param value @@ -154,4 +173,4 @@ inline double makeDouble(quint16 lolo, quint16 lohi, quint16 hilo, quint16 hihi, return v.asDouble; } -#endif // FLOATUTILS_H +#endif // NUMERICUTILS_H diff --git a/omodscan/omodscan.pro b/omodscan/omodscan.pro index c11d324..f529b9b 100644 --- a/omodscan/omodscan.pro +++ b/omodscan/omodscan.pro @@ -21,6 +21,7 @@ win32:RC_ICONS += res/omodscan.ico INCLUDEPATH += controls \ dialogs \ + modbusinfo \ SOURCES += \ controls/booleancombobox.cpp \ @@ -63,10 +64,12 @@ SOURCES += \ dialogs/dialogwriteholdingregister.cpp \ dialogs/dialogwriteholdingregisterbits.cpp \ formmodsca.cpp \ + htmldelegate.cpp \ main.cpp \ mainwindow.cpp \ modbusclient.cpp \ modbusdataunit.cpp \ + modbusinfo/modbuspduinfo.cpp \ modbusrtuscanner.cpp \ modbusscanner.cpp \ modbustcpscanner.cpp \ @@ -120,21 +123,23 @@ HEADERS += \ dialogs/dialogwriteholdingregisterbits.h \ displaydefinition.h \ enums.h \ - floatutils.h \ formatutils.h \ formmodsca.h \ + htmldelegate.h \ mainwindow.h \ + modbusinfo/modbuspduinfo.h \ modbusclient.h \ modbusdataunit.h \ modbusexception.h \ modbusfunction.h \ + modbusinfo/readcoils.h \ modbuslimits.h \ - modbuspduinfo.h \ modbusrtuscanner.h \ modbusscanner.h \ modbussimulationparams.h \ modbustcpscanner.h \ modbuswriteparams.h \ + numericutils.h \ qfixedsizedialog.h \ qhexvalidator.h \ qrange.h \ From 9da71db811ec8d7164b8c4403b9e9a53ff9fc214 Mon Sep 17 00:00:00 2001 From: sanny32 Date: Wed, 27 Sep 2023 16:28:11 +0300 Subject: [PATCH 07/90] Developing new log view --- omodscan/controls/outputwidget.cpp | 262 +++++++++++++++--- omodscan/controls/outputwidget.h | 9 +- omodscan/formatutils.h | 22 +- omodscan/modbusinfo/modbuspduinfo.cpp | 23 -- omodscan/modbusinfo/readcoils.h | 89 ------ omodscan/modbusmessages/diagnostics.h | 76 +++++ omodscan/modbusmessages/getcommeventcounter.h | 60 ++++ omodscan/modbusmessages/getcommeventlog.h | 84 ++++++ omodscan/modbusmessages/modbusmessage.cpp | 66 +++++ .../modbusmessage.h} | 73 ++--- omodscan/modbusmessages/modbusmessages.h | 13 + omodscan/modbusmessages/readcoils.h | 77 +++++ omodscan/modbusmessages/readdiscreteinputs.h | 76 +++++ omodscan/modbusmessages/readexceptionstatus.h | 52 ++++ .../modbusmessages/readholdingregisters.h | 76 +++++ omodscan/modbusmessages/readinputregisters.h | 76 +++++ omodscan/modbusmessages/writemultiplecoils.h | 92 ++++++ .../modbusmessages/writemultipleregisters.h | 92 ++++++ omodscan/modbusmessages/writesinglecoil.h | 76 +++++ omodscan/modbusmessages/writesingleregister.h | 76 +++++ omodscan/omodscan.pro | 20 +- 21 files changed, 1274 insertions(+), 216 deletions(-) delete mode 100644 omodscan/modbusinfo/modbuspduinfo.cpp delete mode 100644 omodscan/modbusinfo/readcoils.h create mode 100644 omodscan/modbusmessages/diagnostics.h create mode 100644 omodscan/modbusmessages/getcommeventcounter.h create mode 100644 omodscan/modbusmessages/getcommeventlog.h create mode 100644 omodscan/modbusmessages/modbusmessage.cpp rename omodscan/{modbusinfo/modbuspduinfo.h => modbusmessages/modbusmessage.h} (55%) create mode 100644 omodscan/modbusmessages/modbusmessages.h create mode 100644 omodscan/modbusmessages/readcoils.h create mode 100644 omodscan/modbusmessages/readdiscreteinputs.h create mode 100644 omodscan/modbusmessages/readexceptionstatus.h create mode 100644 omodscan/modbusmessages/readholdingregisters.h create mode 100644 omodscan/modbusmessages/readinputregisters.h create mode 100644 omodscan/modbusmessages/writemultiplecoils.h create mode 100644 omodscan/modbusmessages/writemultipleregisters.h create mode 100644 omodscan/modbusmessages/writesinglecoil.h create mode 100644 omodscan/modbusmessages/writesingleregister.h diff --git a/omodscan/controls/outputwidget.cpp b/omodscan/controls/outputwidget.cpp index e87f935..16b9fa9 100644 --- a/omodscan/controls/outputwidget.cpp +++ b/omodscan/controls/outputwidget.cpp @@ -5,7 +5,7 @@ #include "formatutils.h" #include "htmldelegate.h" #include "outputwidget.h" -#include "readcoils.h" +#include "modbusmessages.h" #include "ui_outputwidget.h" /// @@ -294,6 +294,17 @@ TrafficModel::TrafficModel(OutputWidget* parent) { } +/// +/// \brief TrafficModel::~TrafficModel +/// +TrafficModel::~TrafficModel() +{ + for(auto&& i : _items) + { + delete i; + } +} + /// /// \brief TrafficModel::columnCount /// \param parent @@ -330,7 +341,7 @@ QVariant TrafficModel::data(const QModelIndex& index, int role) const { case Qt::DisplayRole: return QString("%1 %2 %3").arg(item->timestamp().toString(Qt::ISODateWithMs), - (item->request()? "→" : "←"), + (item->isRequest()? "→" : "←"), item->toString(_parentWidget->dataDisplayMode())); @@ -347,7 +358,13 @@ QVariant TrafficModel::data(const QModelIndex& index, int role) const void TrafficModel::clear() { beginResetModel(); + + for(auto&& i : _items) + { + delete i; + } _items.clear(); + endResetModel(); } @@ -355,7 +372,7 @@ void TrafficModel::clear() /// \brief TrafficModel::append /// \param data /// -void TrafficModel::append(const ModbusPduInfo* data) +void TrafficModel::append(const ModbusMessage* data) { if(data == nullptr) return; @@ -400,13 +417,13 @@ OutputWidget::OutputWidget(QWidget *parent) : if(sel.indexes().isEmpty()) ui->trafficInfo->clear(); else - showTrafficInfo(_trafficModel->data(sel.indexes().first(), Qt::UserRole).value()); + showTrafficInfo(sel.indexes().first()); }); connect(_trafficModel.get(), &TrafficModel::rowsInserted, this, [&](const QModelIndex&, int first, int last) { - const auto index = _trafficModel->index(first); - ui->logView->scrollTo(index); + const auto index = _trafficModel->index(first); + ui->logView->scrollTo(index); }); } @@ -777,7 +794,8 @@ void OutputWidget::setDataDisplayMode(DataDisplayMode mode) _trafficModel->update(); // update traffic info - ui->logView->clicked(ui->logView->currentIndex()); + auto model = ui->logView->selectionModel(); + emit model->selectionChanged(model->selection(), QItemSelection()); } /// @@ -891,77 +909,230 @@ void OutputWidget::captureString(const QString& s) /// /// \brief OutputWidget::showTrafficInfo -/// \param data +/// \param index /// -void OutputWidget::showTrafficInfo(const ModbusPduInfo* data) +void OutputWidget::showTrafficInfo(const QModelIndex& index) { - const auto function = QString("%1 (%2)").arg( - formatByteValue(dataDisplayMode(), data->function()), data->function()); + ui->trafficInfo->clear(); - auto fnPrintException = [&]() - { - const auto exception = QString("%1 (%2)").arg(formatByteValue(dataDisplayMode(), data->exception()), data->exception()); - ui->trafficInfo->addItem(tr("Error Code: %1").arg(formatByteValue(dataDisplayMode(), data->function()))); - ui->trafficInfo->addItem(tr("Exception Code: %1").arg(exception)); - }; + if(!index.isValid()) + return; - ui->trafficInfo->clear(); - ui->trafficInfo->addItem(tr("Type: %1").arg(data->request() ? tr("Tx Message") : tr("Rx Message"))); + const auto data = _trafficModel->data(index, Qt::UserRole).value(); + const auto function = QString("%1 (%2)").arg(formatByteValue(dataDisplayMode(), data->function()), data->function()); + + ui->trafficInfo->addItem(tr("Type: %1").arg(data->isRequest() ? tr("Tx Message") : tr("Rx Message"))); ui->trafficInfo->addItem(tr("Timestamp: %1").arg(data->timestamp().toString(Qt::ISODateWithMs))); ui->trafficInfo->addItem(tr("Device ID: %1").arg(formatByteValue(dataDisplayMode(), data->deviceId()))); + if(data->isException()) + { + const auto exception = QString("%1 (%2)").arg(formatByteValue(dataDisplayMode(), data->exception()), data->exception()); + ui->trafficInfo->addItem(tr("Error Code: %1").arg(formatByteValue(dataDisplayMode(), data->function()))); + ui->trafficInfo->addItem(tr("Exception Code: %1").arg(exception)); + return; + } + + ui->trafficInfo->addItem(tr("Function Code: %1").arg(function)); + switch(data->function()) { case QModbusPdu::ReadCoils: { - if(data->request()) + if(data->isRequest()) + { + auto req = reinterpret_cast(data); + ui->trafficInfo->addItem(tr("Start Address: %1").arg(formatWordValue(dataDisplayMode(), req->startAddress()))); + ui->trafficInfo->addItem(tr("Length: %1").arg(formatWordValue(dataDisplayMode(), req->length()))); + } + else { - auto req = qobject_cast(data); - ui->trafficInfo->addItem(tr("Function Code: %1").arg(function)); - ui->trafficInfo->addItem(tr("Start Address: %1").arg(req->startAddress())); - ui->trafficInfo->addItem(tr("Length: %1").arg(req->length())); + auto resp = reinterpret_cast(data); + ui->trafficInfo->addItem(tr("Byte Count: %1").arg(formatByteValue(dataDisplayMode(), resp->byteCount()))); + ui->trafficInfo->addItem(tr("Coil Status: %1").arg(formatByteArray(dataDisplayMode(), resp->coilStatus()))); } - else if(data->isException()) + } + break; + + case QModbusPdu::ReadDiscreteInputs: + { + if(data->isRequest()) { - fnPrintException(); + auto req = reinterpret_cast(data); + ui->trafficInfo->addItem(tr("Start Address: %1").arg(formatWordValue(dataDisplayMode(), req->startAddress()))); + ui->trafficInfo->addItem(tr("Length: %1").arg(formatWordValue(dataDisplayMode(), req->length()))); } else { - auto resp = qobject_cast(data); - ui->trafficInfo->addItem(tr("Function Code: %1").arg(function)); - ui->trafficInfo->addItem(tr("Byte Count: %1").arg(formatByteValue(dataDisplayMode(), resp->bytesCount()))); - ui->trafficInfo->addItem(tr("Coil Status: %1").arg(formatByteArray(dataDisplayMode(), resp->coilsStatus()))); + auto resp = reinterpret_cast(data); + ui->trafficInfo->addItem(tr("Byte Count: %1").arg(formatByteValue(dataDisplayMode(), resp->byteCount()))); + ui->trafficInfo->addItem(tr("Input Status: %1").arg(formatByteArray(dataDisplayMode(), resp->inputStatus()))); } } break; - /*case QModbusPdu::ReadDiscreteInputs: case QModbusPdu::ReadHoldingRegisters: + { + if(data->isRequest()) + { + auto req = reinterpret_cast(data); + ui->trafficInfo->addItem(tr("Start Address: %1").arg(formatWordValue(dataDisplayMode(), req->startAddress()))); + ui->trafficInfo->addItem(tr("Length: %1").arg(formatWordValue(dataDisplayMode(), req->length()))); + } + else + { + auto resp = reinterpret_cast(data); + ui->trafficInfo->addItem(tr("Byte Count: %1").arg(formatByteValue(dataDisplayMode(), resp->byteCount()))); + ui->trafficInfo->addItem(tr("Register Value: %1").arg(formatByteArray(dataDisplayMode(), resp->registerValue()))); + } + } + break; + case QModbusPdu::ReadInputRegisters: + { + if(data->isRequest()) + { + auto req = reinterpret_cast(data); + ui->trafficInfo->addItem(tr("Start Address: %1").arg(formatWordValue(dataDisplayMode(), req->startAddress()))); + ui->trafficInfo->addItem(tr("Length: %1").arg(formatWordValue(dataDisplayMode(), req->length()))); + } + else + { + auto resp = reinterpret_cast(data); + ui->trafficInfo->addItem(tr("Byte Count: %1").arg(formatByteValue(dataDisplayMode(), resp->byteCount()))); + ui->trafficInfo->addItem(tr("Input Registers: %1").arg(formatByteArray(dataDisplayMode(), resp->registerValue()))); + } + } break; case QModbusPdu::WriteSingleCoil: - ui->trafficInfo->addItem(tr("Output Address: %1").arg(data.startAddress())); - ui->trafficInfo->addItem(tr("Output Value: %1").arg(data.length())); + if(data->isRequest()) + { + auto req = reinterpret_cast(data); + ui->trafficInfo->addItem(tr("Output Address: %1").arg(formatWordValue(dataDisplayMode(), req->address()))); + ui->trafficInfo->addItem(tr("Output Value: %1").arg(formatWordValue(dataDisplayMode(), req->value()))); + } + else + { + auto resp = reinterpret_cast(data); + ui->trafficInfo->addItem(tr("Output Address: %1").arg(formatWordValue(dataDisplayMode(), resp->address()))); + ui->trafficInfo->addItem(tr("Output Value: %1").arg(formatWordValue(dataDisplayMode(), resp->value()))); + } break; case QModbusPdu::WriteSingleRegister: - ui->trafficInfo->addItem(tr("Register Address: %1").arg(data.startAddress())); - ui->trafficInfo->addItem(tr("Register Value: %1").arg(data.length())); + if(data->isRequest()) + { + auto req = reinterpret_cast(data); + ui->trafficInfo->addItem(tr("Register Address: %1").arg(formatWordValue(dataDisplayMode(), req->address()))); + ui->trafficInfo->addItem(tr("Register Value: %1").arg(formatWordValue(dataDisplayMode(), req->value()))); + } + else + { + auto resp = reinterpret_cast(data); + ui->trafficInfo->addItem(tr("Register Address: %1").arg(formatWordValue(dataDisplayMode(), resp->address()))); + ui->trafficInfo->addItem(tr("Register Value: %1").arg(formatWordValue(dataDisplayMode(), resp->value()))); + } + break; + + case QModbusPdu::ReadExceptionStatus: + if(!data->isRequest()) + { + auto resp = reinterpret_cast(data); + ui->trafficInfo->addItem(tr("Output Data: %1").arg(formatByteValue(dataDisplayMode(), resp->outputData()))); + } + break; + + case QModbusPdu::Diagnostics: + if(data->isRequest()) + { + auto req = reinterpret_cast(data); + ui->trafficInfo->addItem(tr("Sub-function: %1").arg(formatWordValue(dataDisplayMode(), req->subfunc()))); + ui->trafficInfo->addItem(tr("Data: %1").arg(formatByteArray(dataDisplayMode(), req->data()))); + } + else + { + auto resp = reinterpret_cast(data); + ui->trafficInfo->addItem(tr("Sub-function: %1").arg(formatWordValue(dataDisplayMode(), resp->subfunc()))); + ui->trafficInfo->addItem(tr("Data: %1").arg(formatByteArray(dataDisplayMode(), resp->data()))); + } + break; + + case QModbusPdu::GetCommEventCounter: + if(!data->isRequest()) + { + auto resp = reinterpret_cast(data); + ui->trafficInfo->addItem(tr("Status: %1").arg(formatWordValue(dataDisplayMode(), resp->status()))); + ui->trafficInfo->addItem(tr("Event Count: %1").arg(formatWordValue(dataDisplayMode(), resp->eventCount()))); + } + break; + + case QModbusPdu::GetCommEventLog: + if(!data->isRequest()) + { + auto resp = reinterpret_cast(data); + ui->trafficInfo->addItem(tr("Byte Count: %1").arg(formatByteValue(dataDisplayMode(), resp->byteCount()))); + ui->trafficInfo->addItem(tr("Status: %1").arg(formatWordValue(dataDisplayMode(), resp->status()))); + ui->trafficInfo->addItem(tr("Event Count: %1").arg(formatWordValue(dataDisplayMode(), resp->eventCount()))); + ui->trafficInfo->addItem(tr("Message Count: %1").arg(formatWordValue(dataDisplayMode(), resp->messageCount()))); + ui->trafficInfo->addItem(tr("Events: %1").arg(formatByteArray(dataDisplayMode(), resp->events()))); + } break; case QModbusPdu::WriteMultipleCoils: - ui->trafficInfo->addItem(tr("Starting Address: %1").arg(data.startAddress())); - ui->trafficInfo->addItem(tr("Quantity of Outputs: %1").arg(data.length())); - ui->trafficInfo->addItem(tr("Byte Count: %1").arg(data.length())); - ui->trafficInfo->addItem(tr("Output Value: %1").arg(data.length())); + if(data->isRequest()) + { + auto req = reinterpret_cast(data); + ui->trafficInfo->addItem(tr("Starting Address: %1").arg(formatWordValue(dataDisplayMode(), req->startAddress()))); + ui->trafficInfo->addItem(tr("Quantity of Outputs: %1").arg(formatWordValue(dataDisplayMode(), req->quantity()))); + ui->trafficInfo->addItem(tr("Byte Count: %1").arg(formatByteValue(dataDisplayMode(), req->byteCount()))); + ui->trafficInfo->addItem(tr("Output Value: %1").arg(formatByteArray(dataDisplayMode(), req->values()))); + } + else + { + auto resp = reinterpret_cast(data); + ui->trafficInfo->addItem(tr("Starting Address: %1").arg(formatWordValue(dataDisplayMode(), resp->startAddress()))); + ui->trafficInfo->addItem(tr("Quantity of Outputs: %1").arg(formatWordValue(dataDisplayMode(), resp->quantity()))); + } break; + case QModbusPdu::WriteMultipleRegisters: - ui->trafficInfo->addItem(tr("Starting Address: %1").arg(data.startAddress())); - ui->trafficInfo->addItem(tr("Quantity of Registers: %1").arg(data.length())); - ui->trafficInfo->addItem(tr("Byte Count: %1").arg(data.length())); - ui->trafficInfo->addItem(tr("Registers Value: %1").arg(data.length())); - break;*/ + if(data->isRequest()) + { + auto req = reinterpret_cast(data); + ui->trafficInfo->addItem(tr("Starting Address: %1").arg(formatWordValue(dataDisplayMode(), req->startAddress()))); + ui->trafficInfo->addItem(tr("Quantity of Registers: %1").arg(formatWordValue(dataDisplayMode(), req->quantity()))); + ui->trafficInfo->addItem(tr("Byte Count: %1").arg(formatByteValue(dataDisplayMode(), req->byteCount()))); + ui->trafficInfo->addItem(tr("Registers Value: %1").arg(formatByteArray(dataDisplayMode(), req->values()))); + } + else + { + auto resp = reinterpret_cast(data); + ui->trafficInfo->addItem(tr("Starting Address: %1").arg(formatWordValue(dataDisplayMode(), resp->startAddress()))); + ui->trafficInfo->addItem(tr("Quantity of Registers: %1").arg(formatWordValue(dataDisplayMode(), resp->quantity()))); + } + break; + + case QModbusPdu::ReportServerId: + break; + + case QModbusPdu::ReadFileRecord: + break; + + case QModbusPdu::WriteFileRecord: + break; + + case QModbusPdu::MaskWriteRegister: + break; + + case QModbusPdu::ReadWriteMultipleRegisters: + break; + + case QModbusPdu::ReadFifoQueue: + break; + + default: + break; } } @@ -972,6 +1143,5 @@ void OutputWidget::showTrafficInfo(const ModbusPduInfo* data) /// void OutputWidget::updateTrafficWidget(bool request, int server, const QModbusPdu& pdu) { - auto info = ModbusPduInfo::create(pdu, QDateTime::currentDateTime(), server, request, this); - _trafficModel->append(info); + _trafficModel->append(ModbusMessage::create(pdu, QDateTime::currentDateTime(), server, request)); } diff --git a/omodscan/controls/outputwidget.h b/omodscan/controls/outputwidget.h index 03f7863..3bef5d2 100644 --- a/omodscan/controls/outputwidget.h +++ b/omodscan/controls/outputwidget.h @@ -7,7 +7,7 @@ #include #include #include "enums.h" -#include "modbuspduinfo.h" +#include "modbusmessage.h" #include "datasimulator.h" #include "displaydefinition.h" @@ -69,20 +69,21 @@ class TrafficModel : public QAbstractListModel public: explicit TrafficModel(OutputWidget* parent); + ~TrafficModel(); int columnCount(const QModelIndex &parent = QModelIndex()) const override; int rowCount(const QModelIndex& parent = QModelIndex()) const override; QVariant data(const QModelIndex& index, int role) const override; void clear(); - void append(const ModbusPduInfo* data); + void append(const ModbusMessage* data); void update(){ emit dataChanged(index(0), index(_items.size() - 1)); } private: OutputWidget* _parentWidget; - QVector _items; + QVector _items; }; /// @@ -156,7 +157,7 @@ private slots: private: void setUninitializedStatus(); void captureString(const QString& s); - void showTrafficInfo(const ModbusPduInfo* data); + void showTrafficInfo(const QModelIndex& index); void updateTrafficWidget(bool request, int server, const QModbusPdu& pdu); private: diff --git a/omodscan/formatutils.h b/omodscan/formatutils.h index d7ad89e..2b09842 100644 --- a/omodscan/formatutils.h +++ b/omodscan/formatutils.h @@ -14,7 +14,8 @@ /// \param c /// \return /// -inline QString formatByteValue(DataDisplayMode mode, uchar c) { +inline QString formatByteValue(DataDisplayMode mode, uchar c) +{ switch(mode) { case DataDisplayMode::Decimal: @@ -41,6 +42,25 @@ inline QString formatByteArray(DataDisplayMode mode, const QByteArray& ar) return values.join(" "); } +/// +/// \brief formatWordValue +/// \param mode +/// \param v +/// \return +/// +inline QString formatWordValue(DataDisplayMode mode, quint16 v) +{ + switch(mode) + { + case DataDisplayMode::Decimal: + case DataDisplayMode::Integer: + return QString("%1").arg(QString::number(v), 3, '0'); + + default: + return QString("%1").arg(QString::number(v, 16).toUpper(), 2, '0'); + } +} + /// /// \brief formatBinaryValue /// \param pointType diff --git a/omodscan/modbusinfo/modbuspduinfo.cpp b/omodscan/modbusinfo/modbuspduinfo.cpp deleted file mode 100644 index dd94abf..0000000 --- a/omodscan/modbusinfo/modbuspduinfo.cpp +++ /dev/null @@ -1,23 +0,0 @@ -#include "modbuspduinfo.h" -#include "readcoils.h" - -/// -/// \brief ModbusPduInfo::create -/// \param pdu -/// \param timestamp -/// \param deviceId -/// \param request -/// \return -/// -const ModbusPduInfo* ModbusPduInfo::create(const QModbusPdu& pdu, const QDateTime& timestamp, int deviceId, bool request, QObject* parent) -{ - switch(pdu.functionCode()) - { - case QModbusPdu::ReadCoils: - if(request) return new ReadCoilsRequest(pdu, timestamp, deviceId, parent); - else return new ReadCoilsResponse(pdu, timestamp, deviceId, parent); - - default: - return nullptr; - } -} diff --git a/omodscan/modbusinfo/readcoils.h b/omodscan/modbusinfo/readcoils.h deleted file mode 100644 index 3e3547a..0000000 --- a/omodscan/modbusinfo/readcoils.h +++ /dev/null @@ -1,89 +0,0 @@ -#ifndef READCOILS_H -#define READCOILS_H - -#include "numericutils.h" -#include "modbuspduinfo.h" - -/// -/// \brief The ReadCoilsRequest class -/// -class ReadCoilsRequest : public ModbusPduInfo -{ - Q_OBJECT -public: - /// - /// \brief ReadCoilsRequest - /// - explicit ReadCoilsRequest() = default; - - /// - /// \brief ReadCoilsRequest - /// \param pdu - /// \param timestamp - /// \param deviceId - /// - ReadCoilsRequest(const QModbusPdu& pdu, const QDateTime& timestamp, int deviceId, QObject* parent) - : ModbusPduInfo(pdu, timestamp, deviceId, true, parent) - { - Q_ASSERT(_funcCode == QModbusPdu::ReadCoils); - } - - /// - /// \brief startAddress - /// \return - /// - quint16 startAddress() const { - return makeWord(_data[1], _data[2], ByteOrder::LittleEndian); - } - - /// - /// \brief length - /// \return - /// - quint16 length() const { - return makeWord(_data[3], _data[4], ByteOrder::LittleEndian); - } -}; - -/// -/// \brief The ReadCoilsResponse class -/// -class ReadCoilsResponse : public ModbusPduInfo -{ - Q_OBJECT -public: - /// - /// \brief ReadCoilsResponse - /// - explicit ReadCoilsResponse() = default; - - /// - /// \brief ReadCoilsResponse - /// \param pdu - /// \param timestamp - /// \param deviceId - /// - ReadCoilsResponse(const QModbusPdu& pdu, const QDateTime& timestamp, int deviceId, QObject* parent) - :ModbusPduInfo(pdu, timestamp, deviceId, false, parent) - { - Q_ASSERT(_funcCode == QModbusPdu::ReadCoils); - } - - /// - /// \brief bytesCount - /// \return - /// - quint8 bytesCount() const { - return _data[1]; - } - - /// - /// \brief coilsStatus - /// \return - /// - QByteArray coilsStatus() const { - return QByteArray(_data + 2, _data.size() - 2); - } -}; - -#endif // READCOILS_H diff --git a/omodscan/modbusmessages/diagnostics.h b/omodscan/modbusmessages/diagnostics.h new file mode 100644 index 0000000..1184e50 --- /dev/null +++ b/omodscan/modbusmessages/diagnostics.h @@ -0,0 +1,76 @@ +#ifndef DIAGNOSTICS_H +#define DIAGNOSTICS_H + +#include "modbusmessage.h" + +/// +/// \brief The DiagnosticsRequest class +/// +class DiagnosticsRequest : public ModbusMessage +{ +public: + /// + /// \brief DiagnosticsRequest + /// \param pdu + /// \param timestamp + /// \param deviceId + /// + DiagnosticsRequest(const QModbusPdu& pdu, const QDateTime& timestamp, int deviceId) + : ModbusMessage(pdu, timestamp, deviceId, true) + { + Q_ASSERT((_funcCode & ~QModbusPdu::ExceptionByte) == QModbusPdu::Diagnostics); + } + + /// + /// \brief subfunc + /// \return + /// + quint16 subfunc() const { + return makeWord(_data[1], _data[0], ByteOrder::LittleEndian); + } + + /// + /// \brief data + /// \return + /// + QByteArray data() const { + return _data.right(_data.size() - 2); + } +}; + +/// +/// \brief The DiagnosticsResponse class +/// +class DiagnosticsResponse : public ModbusMessage +{ +public: + /// + /// \brief DiagnosticsResponse + /// \param pdu + /// \param timestamp + /// \param deviceId + /// + DiagnosticsResponse(const QModbusPdu& pdu, const QDateTime& timestamp, int deviceId) + :ModbusMessage(pdu, timestamp, deviceId, false) + { + Q_ASSERT((_funcCode & ~QModbusPdu::ExceptionByte) == QModbusPdu::Diagnostics); + } + + /// + /// \brief subfunc + /// \return + /// + quint16 subfunc() const { + return makeWord(_data[1], _data[0], ByteOrder::LittleEndian); + } + + /// + /// \brief data + /// \return + /// + QByteArray data() const { + return _data.right(_data.size() - 2); + } +}; + +#endif // DIAGNOSTICS_H diff --git a/omodscan/modbusmessages/getcommeventcounter.h b/omodscan/modbusmessages/getcommeventcounter.h new file mode 100644 index 0000000..4b881c0 --- /dev/null +++ b/omodscan/modbusmessages/getcommeventcounter.h @@ -0,0 +1,60 @@ +#ifndef GETCOMMEVENTCOUNTER_H +#define GETCOMMEVENTCOUNTER_H + +#include "modbusmessage.h" + +/// +/// \brief The GetCommEventCounterRequest class +/// +class GetCommEventCounterRequest : public ModbusMessage +{ +public: + /// + /// \brief GetCommEventCounterRequest + /// \param pdu + /// \param timestamp + /// \param deviceId + /// + GetCommEventCounterRequest(const QModbusPdu& pdu, const QDateTime& timestamp, int deviceId) + : ModbusMessage(pdu, timestamp, deviceId, true) + { + Q_ASSERT((_funcCode & ~QModbusPdu::ExceptionByte) == QModbusPdu::GetCommEventCounter); + } +}; + +/// +/// \brief The GetCommEventCounterResponse class +/// +class GetCommEventCounterResponse : public ModbusMessage +{ +public: + /// + /// \brief GetCommEventCounterResponse + /// \param pdu + /// \param timestamp + /// \param deviceId + /// + GetCommEventCounterResponse(const QModbusPdu& pdu, const QDateTime& timestamp, int deviceId) + :ModbusMessage(pdu, timestamp, deviceId, false) + { + Q_ASSERT((_funcCode & ~QModbusPdu::ExceptionByte) == QModbusPdu::GetCommEventCounter); + } + + /// + /// \brief status + /// \return + /// + quint16 status() const { + return makeWord(_data[1], _data[0], ByteOrder::LittleEndian); + } + + /// + /// \brief eventCount + /// \return + /// + quint16 eventCount() const { + return makeWord(_data[3], _data[2], ByteOrder::LittleEndian); + } +}; + +#endif // GETCOMMEVENTCOUNTER_H diff --git a/omodscan/modbusmessages/getcommeventlog.h b/omodscan/modbusmessages/getcommeventlog.h new file mode 100644 index 0000000..b15d0aa --- /dev/null +++ b/omodscan/modbusmessages/getcommeventlog.h @@ -0,0 +1,84 @@ +#ifndef GETCOMMEVENTLOG_H +#define GETCOMMEVENTLOG_H + +#include "modbusmessage.h" + +/// +/// \brief The GetCommEventLogRequest class +/// +class GetCommEventLogRequest : public ModbusMessage +{ +public: + /// + /// \brief GetCommEventLogRequest + /// \param pdu + /// \param timestamp + /// \param deviceId + /// + GetCommEventLogRequest(const QModbusPdu& pdu, const QDateTime& timestamp, int deviceId) + : ModbusMessage(pdu, timestamp, deviceId, true) + { + Q_ASSERT((_funcCode & ~QModbusPdu::ExceptionByte) == QModbusPdu::GetCommEventLog); + } +}; + +/// +/// \brief The GetCommEventLogResponse class +/// +class GetCommEventLogResponse : public ModbusMessage +{ +public: + /// + /// \brief GetCommEventLogResponse + /// \param pdu + /// \param timestamp + /// \param deviceId + /// + GetCommEventLogResponse(const QModbusPdu& pdu, const QDateTime& timestamp, int deviceId) + :ModbusMessage(pdu, timestamp, deviceId, false) + { + Q_ASSERT((_funcCode & ~QModbusPdu::ExceptionByte) == QModbusPdu::GetCommEventLog); + } + + /// + /// \brief byteCount + /// \return + /// + quint8 byteCount() const { + return _data[0]; + } + + /// + /// \brief status + /// \return + /// + quint16 status() const { + return makeWord(_data[2], _data[1], ByteOrder::LittleEndian); + } + + /// + /// \brief eventCount + /// \return + /// + quint16 eventCount() const { + return makeWord(_data[4], _data[3], ByteOrder::LittleEndian); + } + + /// + /// \brief messageCount + /// \return + /// + quint16 messageCount() const { + return makeWord(_data[6], _data[5], ByteOrder::LittleEndian); + } + + /// + /// \brief events + /// \return + /// + QByteArray events() const { + return _data.right(_data.size() - 7); + } +}; + +#endif // GETCOMMEVENTLOG_H diff --git a/omodscan/modbusmessages/modbusmessage.cpp b/omodscan/modbusmessages/modbusmessage.cpp new file mode 100644 index 0000000..1096373 --- /dev/null +++ b/omodscan/modbusmessages/modbusmessage.cpp @@ -0,0 +1,66 @@ +#include "modbusmessages.h" + +/// +/// \brief ModbusMessage::create +/// \param pdu +/// \param timestamp +/// \param deviceId +/// \param request +/// \return +/// +const ModbusMessage* ModbusMessage::create(const QModbusPdu& pdu, const QDateTime& timestamp, int deviceId, bool request) +{ + switch(pdu.functionCode()) + { + case QModbusPdu::ReadCoils: + if(request) return new ReadCoilsRequest(pdu, timestamp, deviceId); + else return new ReadCoilsResponse(pdu, timestamp, deviceId); + + case QModbusPdu::ReadDiscreteInputs: + if(request) return new ReadDiscreteInputsRequest(pdu, timestamp, deviceId); + else return new ReadDiscreteInputsResponse(pdu, timestamp, deviceId); + + case QModbusPdu::ReadHoldingRegisters: + if(request) return new ReadHoldingRegistersRequest(pdu, timestamp, deviceId); + else return new ReadHoldingRegistersResponse(pdu, timestamp, deviceId); + + case QModbusPdu::ReadInputRegisters: + if(request) return new ReadInputRegistersRequest(pdu, timestamp, deviceId); + else return new ReadInputRegistersResponse(pdu, timestamp, deviceId); + + case QModbusPdu::WriteSingleCoil: + if(request) return new WriteSingleCoilRequest(pdu, timestamp, deviceId); + else return new WriteSingleCoilResponse(pdu, timestamp, deviceId); + + case QModbusPdu::WriteSingleRegister: + if(request) return new WriteSingleRegisterRequest(pdu, timestamp, deviceId); + else return new WriteSingleRegisterResponse(pdu, timestamp, deviceId); + + case QModbusPdu::ReadExceptionStatus: + if(request) return new ReadExceptionStatusRequest(pdu, timestamp, deviceId); + else return new ReadExceptionStatusResponse(pdu, timestamp, deviceId); + + case QModbusPdu::Diagnostics: + if(request) return new DiagnosticsRequest(pdu, timestamp, deviceId); + else return new DiagnosticsResponse(pdu, timestamp, deviceId); + + case QModbusPdu::GetCommEventCounter: + if(request) return new GetCommEventCounterRequest(pdu, timestamp, deviceId); + else return new GetCommEventCounterResponse(pdu, timestamp, deviceId); + + case QModbusPdu::GetCommEventLog: + if(request) return new GetCommEventLogRequest(pdu, timestamp, deviceId); + else return new GetCommEventLogResponse(pdu, timestamp, deviceId); + + case QModbusPdu::WriteMultipleCoils: + if(request) return new WriteMultipleCoilsRequest(pdu, timestamp, deviceId); + else return new WriteMultipleCoilsResponse(pdu, timestamp, deviceId); + + case QModbusPdu::WriteMultipleRegisters: + if(request) return new WriteMultipleRegistersRequest(pdu, timestamp, deviceId); + else return new WriteMultipleRegistersResponse(pdu, timestamp, deviceId); + + default: + return nullptr; + } +} diff --git a/omodscan/modbusinfo/modbuspduinfo.h b/omodscan/modbusmessages/modbusmessage.h similarity index 55% rename from omodscan/modbusinfo/modbuspduinfo.h rename to omodscan/modbusmessages/modbusmessage.h index f94d863..eb0c330 100644 --- a/omodscan/modbusinfo/modbuspduinfo.h +++ b/omodscan/modbusmessages/modbusmessage.h @@ -1,5 +1,5 @@ -#ifndef MODBUSPDUINFO_H -#define MODBUSPDUINFO_H +#ifndef MODBUSMESSAGE_H +#define MODBUSMESSAGE_H #include #include @@ -8,16 +8,15 @@ #include "modbusexception.h" /// -/// \brief The ModbusPduInfo class +/// \brief The ModbusMessage class /// -class ModbusPduInfo: public QObject +class ModbusMessage { - Q_OBJECT public: /// - /// \brief ModbusPduInfo + /// \brief ~ModbusMessage /// - explicit ModbusPduInfo() = default; + virtual ~ModbusMessage() = default; /// /// \brief create @@ -27,7 +26,7 @@ class ModbusPduInfo: public QObject /// \param request /// \return /// - static const ModbusPduInfo* create(const QModbusPdu& pdu, const QDateTime& timestamp, int deviceId, bool request, QObject* parent = nullptr); + static const ModbusMessage* create(const QModbusPdu& pdu, const QDateTime& timestamp, int deviceId, bool request); /// /// \brief isValid @@ -49,7 +48,7 @@ class ModbusPduInfo: public QObject /// \brief request /// \return /// - bool request() const { + bool isRequest() const { return _request; } @@ -57,7 +56,7 @@ class ModbusPduInfo: public QObject /// \brief deviceId /// \return /// - bool deviceId() const { + int deviceId() const { return _deviceId; } @@ -85,14 +84,6 @@ class ModbusPduInfo: public QObject return ModbusException((QModbusPdu::ExceptionCode)_exceptionCode); } - /// - /// \brief data - /// \return - /// - QByteArray data() const { - return _data; - } - /// /// \brief toString /// \param mode @@ -111,49 +102,33 @@ class ModbusPduInfo: public QObject return data.join(" "); } - /// - /// \brief registerValues - /// \param mode - /// \return - /// - QString registerValues(DataDisplayMode mode) const { - if(_request) return QString(); - - QStringList values; - for(auto i = 1; i < _data.size(); i++) - values += formatByteValue(mode, _data[i]); - - return values.join(" "); - } - protected: /// - /// \brief ModbusPduInfo + /// \brief ModbusMessage /// \param pdu /// \param timestamp /// \param deviceId /// \param request /// - ModbusPduInfo(const QModbusPdu& pdu, const QDateTime& timestamp, int deviceId, bool request, QObject* parent = nullptr) - : QObject(parent) + ModbusMessage(const QModbusPdu& pdu, const QDateTime& timestamp, int deviceId, bool request) + :_data(pdu.data()) + ,_funcCode(pdu.isException() ? (pdu.functionCode() | QModbusPdu::ExceptionByte) : pdu.functionCode()) + ,_exceptionCode(pdu.exceptionCode()) + ,_timestamp(timestamp) + ,_deviceId(deviceId) + ,_request(request) { - _timestamp = timestamp; - _deviceId = deviceId; - _request = request; - _funcCode = pdu.isException() ? (pdu.functionCode() | QModbusPdu::ExceptionByte) : pdu.functionCode(); - _exceptionCode = pdu.exceptionCode(); - _data = pdu.data(); } protected: - QByteArray _data; - quint8 _funcCode; - quint8 _exceptionCode; + const QByteArray _data; + const quint8 _funcCode; + const quint8 _exceptionCode; private: - QDateTime _timestamp; - int _deviceId = -1; - bool _request = false; + const QDateTime _timestamp; + const int _deviceId; + const bool _request; }; -#endif // MODBUSPDUINFO_H +#endif // MODBUSMESSAGE_H diff --git a/omodscan/modbusmessages/modbusmessages.h b/omodscan/modbusmessages/modbusmessages.h new file mode 100644 index 0000000..4e42604 --- /dev/null +++ b/omodscan/modbusmessages/modbusmessages.h @@ -0,0 +1,13 @@ +#include "modbusmessage.h" +#include "readcoils.h" +#include "readdiscreteinputs.h" +#include "readholdingregisters.h" +#include "readinputregisters.h" +#include "writesinglecoil.h" +#include "writesingleregister.h" +#include "readexceptionstatus.h" +#include "diagnostics.h" +#include "getcommeventcounter.h" +#include "getcommeventlog.h" +#include "writemultiplecoils.h" +#include "writemultipleregisters.h" diff --git a/omodscan/modbusmessages/readcoils.h b/omodscan/modbusmessages/readcoils.h new file mode 100644 index 0000000..cf53a2f --- /dev/null +++ b/omodscan/modbusmessages/readcoils.h @@ -0,0 +1,77 @@ +#ifndef READCOILS_H +#define READCOILS_H + +#include "numericutils.h" +#include "modbusmessage.h" + +/// +/// \brief The ReadCoilsRequest class +/// +class ReadCoilsRequest : public ModbusMessage +{ +public: + /// + /// \brief ReadCoilsRequest + /// \param pdu + /// \param timestamp + /// \param deviceId + /// + ReadCoilsRequest(const QModbusPdu& pdu, const QDateTime& timestamp, int deviceId) + : ModbusMessage(pdu, timestamp, deviceId, true) + { + Q_ASSERT((_funcCode & ~QModbusPdu::ExceptionByte) == QModbusPdu::ReadCoils); + } + + /// + /// \brief startAddress + /// \return + /// + quint16 startAddress() const { + return makeWord(_data[1], _data[0], ByteOrder::LittleEndian); + } + + /// + /// \brief length + /// \return + /// + quint16 length() const { + return makeWord(_data[3], _data[2], ByteOrder::LittleEndian); + } +}; + +/// +/// \brief The ReadCoilsResponse class +/// +class ReadCoilsResponse : public ModbusMessage +{ +public: + /// + /// \brief ReadCoilsResponse + /// \param pdu + /// \param timestamp + /// \param deviceId + /// + ReadCoilsResponse(const QModbusPdu& pdu, const QDateTime& timestamp, int deviceId) + :ModbusMessage(pdu, timestamp, deviceId, false) + { + Q_ASSERT((_funcCode & ~QModbusPdu::ExceptionByte) == QModbusPdu::ReadCoils); + } + + /// + /// \brief byteCount + /// \return + /// + quint8 byteCount() const { + return _data[0]; + } + + /// + /// \brief coilStatus + /// \return + /// + QByteArray coilStatus() const { + return _data.right(_data.size() - 1); + } +}; + +#endif // READCOILS_H diff --git a/omodscan/modbusmessages/readdiscreteinputs.h b/omodscan/modbusmessages/readdiscreteinputs.h new file mode 100644 index 0000000..2926924 --- /dev/null +++ b/omodscan/modbusmessages/readdiscreteinputs.h @@ -0,0 +1,76 @@ +#ifndef READDISCRETEINPUTS_H +#define READDISCRETEINPUTS_H + +#include "modbusmessage.h" + +/// +/// \brief The ReadDiscreteInputsRequest class +/// +class ReadDiscreteInputsRequest : public ModbusMessage +{ +public: + /// + /// \brief ReadDiscreteInputsRequest + /// \param pdu + /// \param timestamp + /// \param deviceId + /// + ReadDiscreteInputsRequest(const QModbusPdu& pdu, const QDateTime& timestamp, int deviceId) + : ModbusMessage(pdu, timestamp, deviceId, true) + { + Q_ASSERT((_funcCode & ~QModbusPdu::ExceptionByte) == QModbusPdu::ReadDiscreteInputs); + } + + /// + /// \brief startAddress + /// \return + /// + quint16 startAddress() const { + return makeWord(_data[1], _data[0], ByteOrder::LittleEndian); + } + + /// + /// \brief length + /// \return + /// + quint16 length() const { + return makeWord(_data[3], _data[2], ByteOrder::LittleEndian); + } +}; + +/// +/// \brief The ReadDiscreteInputsResponse class +/// +class ReadDiscreteInputsResponse : public ModbusMessage +{ +public: + /// + /// \brief ReadDiscreteInputsResponse + /// \param pdu + /// \param timestamp + /// \param deviceId + /// + ReadDiscreteInputsResponse(const QModbusPdu& pdu, const QDateTime& timestamp, int deviceId) + :ModbusMessage(pdu, timestamp, deviceId, false) + { + Q_ASSERT((_funcCode & ~QModbusPdu::ExceptionByte) == QModbusPdu::ReadDiscreteInputs); + } + + /// + /// \brief byteCount + /// \return + /// + quint8 byteCount() const { + return _data[0]; + } + + /// + /// \brief inputStatus + /// \return + /// + QByteArray inputStatus() const { + return _data.right(_data.size() - 1); + } +}; + +#endif // READDISCRETEINPUTS_H diff --git a/omodscan/modbusmessages/readexceptionstatus.h b/omodscan/modbusmessages/readexceptionstatus.h new file mode 100644 index 0000000..a95972e --- /dev/null +++ b/omodscan/modbusmessages/readexceptionstatus.h @@ -0,0 +1,52 @@ +#ifndef READEXCEPTIONSTATUS_H +#define READEXCEPTIONSTATUS_H + +#include "modbusmessage.h" + +/// +/// \brief The ReadExceptionStatusRequest class +/// +class ReadExceptionStatusRequest : public ModbusMessage +{ +public: + /// + /// \brief ReadExceptionStatusRequest + /// \param pdu + /// \param timestamp + /// \param deviceId + /// + ReadExceptionStatusRequest(const QModbusPdu& pdu, const QDateTime& timestamp, int deviceId) + : ModbusMessage(pdu, timestamp, deviceId, true) + { + Q_ASSERT((_funcCode & ~QModbusPdu::ExceptionByte) == QModbusPdu::ReadExceptionStatus); + } +}; + +/// +/// \brief The ReadExceptionStatusResponse class +/// +class ReadExceptionStatusResponse : public ModbusMessage +{ +public: + /// + /// \brief ReadExceptionStatusResponse + /// \param pdu + /// \param timestamp + /// \param deviceId + /// + ReadExceptionStatusResponse(const QModbusPdu& pdu, const QDateTime& timestamp, int deviceId) + :ModbusMessage(pdu, timestamp, deviceId, false) + { + Q_ASSERT((_funcCode & ~QModbusPdu::ExceptionByte) == QModbusPdu::ReadExceptionStatus); + } + + /// + /// \brief outputData + /// \return + /// + quint8 outputData() const { + return _data[0]; + } +}; + +#endif // READEXCEPTIONSTATUS_H diff --git a/omodscan/modbusmessages/readholdingregisters.h b/omodscan/modbusmessages/readholdingregisters.h new file mode 100644 index 0000000..8047021 --- /dev/null +++ b/omodscan/modbusmessages/readholdingregisters.h @@ -0,0 +1,76 @@ +#ifndef READHOLDINGREGISTERS_H +#define READHOLDINGREGISTERS_H + +#include "modbusmessage.h" + +/// +/// \brief The ReadHoldingRegistersRequest class +/// +class ReadHoldingRegistersRequest : public ModbusMessage +{ +public: + /// + /// \brief ReadHoldingRegistersRequest + /// \param pdu + /// \param timestamp + /// \param deviceId + /// + ReadHoldingRegistersRequest(const QModbusPdu& pdu, const QDateTime& timestamp, int deviceId) + : ModbusMessage(pdu, timestamp, deviceId, true) + { + Q_ASSERT((_funcCode & ~QModbusPdu::ExceptionByte) == QModbusPdu::ReadHoldingRegisters); + } + + /// + /// \brief startAddress + /// \return + /// + quint16 startAddress() const { + return makeWord(_data[1], _data[0], ByteOrder::LittleEndian); + } + + /// + /// \brief length + /// \return + /// + quint16 length() const { + return makeWord(_data[3], _data[2], ByteOrder::LittleEndian); + } +}; + +/// +/// \brief The ReadHoldingRegistersResponse class +/// +class ReadHoldingRegistersResponse : public ModbusMessage +{ +public: + /// + /// \brief ReadHoldingRegistersResponse + /// \param pdu + /// \param timestamp + /// \param deviceId + /// + ReadHoldingRegistersResponse(const QModbusPdu& pdu, const QDateTime& timestamp, int deviceId) + :ModbusMessage(pdu, timestamp, deviceId, false) + { + Q_ASSERT((_funcCode & ~QModbusPdu::ExceptionByte) == QModbusPdu::ReadHoldingRegisters); + } + + /// + /// \brief byteCount + /// \return + /// + quint8 byteCount() const { + return _data[0]; + } + + /// + /// \brief registerValue + /// \return + /// + QByteArray registerValue() const { + return _data.right(_data.size() - 1); + } +}; + +#endif // READHOLDINGREGISTERS_H diff --git a/omodscan/modbusmessages/readinputregisters.h b/omodscan/modbusmessages/readinputregisters.h new file mode 100644 index 0000000..701937e --- /dev/null +++ b/omodscan/modbusmessages/readinputregisters.h @@ -0,0 +1,76 @@ +#ifndef READINPUTREGISTERS_H +#define READINPUTREGISTERS_H + +#include "modbusmessage.h" + +/// +/// \brief The ReadInputRegistersRequest class +/// +class ReadInputRegistersRequest : public ModbusMessage +{ +public: + /// + /// \brief ReadInputRegistersRequest + /// \param pdu + /// \param timestamp + /// \param deviceId + /// + ReadInputRegistersRequest(const QModbusPdu& pdu, const QDateTime& timestamp, int deviceId) + : ModbusMessage(pdu, timestamp, deviceId, true) + { + Q_ASSERT((_funcCode & ~QModbusPdu::ExceptionByte) == QModbusPdu::ReadInputRegisters); + } + + /// + /// \brief startAddress + /// \return + /// + quint16 startAddress() const { + return makeWord(_data[1], _data[0], ByteOrder::LittleEndian); + } + + /// + /// \brief length + /// \return + /// + quint16 length() const { + return makeWord(_data[3], _data[2], ByteOrder::LittleEndian); + } +}; + +/// +/// \brief The ReadInputRegistersResponse class +/// +class ReadInputRegistersResponse : public ModbusMessage +{ +public: + /// + /// \brief ReadInputRegistersResponse + /// \param pdu + /// \param timestamp + /// \param deviceId + /// + ReadInputRegistersResponse(const QModbusPdu& pdu, const QDateTime& timestamp, int deviceId) + :ModbusMessage(pdu, timestamp, deviceId, false) + { + Q_ASSERT((_funcCode & ~QModbusPdu::ExceptionByte) == QModbusPdu::ReadInputRegisters); + } + + /// + /// \brief byteCount + /// \return + /// + quint8 byteCount() const { + return _data[0]; + } + + /// + /// \brief registerValue + /// \return + /// + QByteArray registerValue() const { + return _data.right(_data.size() - 1); + } +}; + +#endif // READINPUTREGISTERS_H diff --git a/omodscan/modbusmessages/writemultiplecoils.h b/omodscan/modbusmessages/writemultiplecoils.h new file mode 100644 index 0000000..0308461 --- /dev/null +++ b/omodscan/modbusmessages/writemultiplecoils.h @@ -0,0 +1,92 @@ +#ifndef WRITEMULTIPLECOILS_H +#define WRITEMULTIPLECOILS_H + +#include "modbusmessage.h" + +/// +/// \brief The WriteMultipleCoilsRequest class +/// +class WriteMultipleCoilsRequest : public ModbusMessage +{ +public: + /// + /// \brief WriteMultipleCoilsRequest + /// \param pdu + /// \param timestamp + /// \param deviceId + /// + WriteMultipleCoilsRequest(const QModbusPdu& pdu, const QDateTime& timestamp, int deviceId) + : ModbusMessage(pdu, timestamp, deviceId, true) + { + Q_ASSERT((_funcCode & ~QModbusPdu::ExceptionByte) == QModbusPdu::WriteMultipleCoils); + } + + /// + /// \brief startAddress + /// \return + /// + quint16 startAddress() const { + return makeWord(_data[1], _data[0], ByteOrder::LittleEndian); + } + + /// + /// \brief quantity + /// \return + /// + quint16 quantity() const { + return makeWord(_data[3], _data[2], ByteOrder::LittleEndian); + } + + /// + /// \brief byteCount + /// \return + /// + quint8 byteCount() const { + return _data[4]; + } + + /// + /// \brief values + /// \return + /// + QByteArray values() const { + return _data.right(_data.size() - 5); + } +}; + +/// +/// \brief The WriteMultipleCoilsResponse class +/// +class WriteMultipleCoilsResponse : public ModbusMessage +{ +public: + /// + /// \brief WriteMultipleCoilsResponse + /// \param pdu + /// \param timestamp + /// \param deviceId + /// + WriteMultipleCoilsResponse(const QModbusPdu& pdu, const QDateTime& timestamp, int deviceId) + :ModbusMessage(pdu, timestamp, deviceId, false) + { + Q_ASSERT((_funcCode & ~QModbusPdu::ExceptionByte) == QModbusPdu::WriteMultipleCoils); + } + + /// + /// \brief startAddress + /// \return + /// + quint16 startAddress() const { + return makeWord(_data[1], _data[0], ByteOrder::LittleEndian); + } + + /// + /// \brief quantity + /// \return + /// + quint16 quantity() const { + return makeWord(_data[3], _data[2], ByteOrder::LittleEndian); + } +}; + +#endif // WRITEMULTIPLECOILS_H diff --git a/omodscan/modbusmessages/writemultipleregisters.h b/omodscan/modbusmessages/writemultipleregisters.h new file mode 100644 index 0000000..5952515 --- /dev/null +++ b/omodscan/modbusmessages/writemultipleregisters.h @@ -0,0 +1,92 @@ +#ifndef WRITEMULTIPLEREGISTERS_H +#define WRITEMULTIPLEREGISTERS_H + +#include "modbusmessage.h" + +/// +/// \brief The WriteMultipleRegistersRequest class +/// +class WriteMultipleRegistersRequest : public ModbusMessage +{ +public: + /// + /// \brief WriteMultipleRegistersRequest + /// \param pdu + /// \param timestamp + /// \param deviceId + /// + WriteMultipleRegistersRequest(const QModbusPdu& pdu, const QDateTime& timestamp, int deviceId) + : ModbusMessage(pdu, timestamp, deviceId, true) + { + Q_ASSERT((_funcCode & ~QModbusPdu::ExceptionByte) == QModbusPdu::WriteMultipleRegisters); + } + + /// + /// \brief startAddress + /// \return + /// + quint16 startAddress() const { + return makeWord(_data[1], _data[0], ByteOrder::LittleEndian); + } + + /// + /// \brief quantity + /// \return + /// + quint16 quantity() const { + return makeWord(_data[3], _data[2], ByteOrder::LittleEndian); + } + + /// + /// \brief byteCount + /// \return + /// + quint8 byteCount() const { + return _data[4]; + } + + /// + /// \brief values + /// \return + /// + QByteArray values() const { + return _data.right(_data.size() - 5); + } +}; + +/// +/// \brief The WriteMultipleRegistersResponse class +/// +class WriteMultipleRegistersResponse : public ModbusMessage +{ +public: + /// + /// \brief WriteMultipleRegistersResponse + /// \param pdu + /// \param timestamp + /// \param deviceId + /// + WriteMultipleRegistersResponse(const QModbusPdu& pdu, const QDateTime& timestamp, int deviceId) + :ModbusMessage(pdu, timestamp, deviceId, false) + { + Q_ASSERT((_funcCode & ~QModbusPdu::ExceptionByte) == QModbusPdu::WriteMultipleRegisters); + } + + /// + /// \brief startAddress + /// \return + /// + quint16 startAddress() const { + return makeWord(_data[1], _data[0], ByteOrder::LittleEndian); + } + + /// + /// \brief quantity + /// \return + /// + quint16 quantity() const { + return makeWord(_data[3], _data[2], ByteOrder::LittleEndian); + } +}; + +#endif // WRITEMULTIPLEREGISTERS_H diff --git a/omodscan/modbusmessages/writesinglecoil.h b/omodscan/modbusmessages/writesinglecoil.h new file mode 100644 index 0000000..de26fca --- /dev/null +++ b/omodscan/modbusmessages/writesinglecoil.h @@ -0,0 +1,76 @@ +#ifndef WRITESINGLECOIL_H +#define WRITESINGLECOIL_H + +#include "modbusmessage.h" + +/// +/// \brief The WriteSingleCoilRequest class +/// +class WriteSingleCoilRequest : public ModbusMessage +{ +public: + /// + /// \brief WriteSingleCoilRequest + /// \param pdu + /// \param timestamp + /// \param deviceId + /// + WriteSingleCoilRequest(const QModbusPdu& pdu, const QDateTime& timestamp, int deviceId) + : ModbusMessage(pdu, timestamp, deviceId, true) + { + Q_ASSERT((_funcCode & ~QModbusPdu::ExceptionByte) == QModbusPdu::WriteSingleCoil); + } + + /// + /// \brief address + /// \return + /// + quint16 address() const { + return makeWord(_data[1], _data[0], ByteOrder::LittleEndian); + } + + /// + /// \brief value + /// \return + /// + quint16 value() const { + return makeWord(_data[3], _data[2], ByteOrder::LittleEndian); + } +}; + +/// +/// \brief The WriteSingleCoilResponse class +/// +class WriteSingleCoilResponse : public ModbusMessage +{ +public: + /// + /// \brief WriteSingleCoilResponse + /// \param pdu + /// \param timestamp + /// \param deviceId + /// + WriteSingleCoilResponse(const QModbusPdu& pdu, const QDateTime& timestamp, int deviceId) + :ModbusMessage(pdu, timestamp, deviceId, false) + { + Q_ASSERT((_funcCode & ~QModbusPdu::ExceptionByte) == QModbusPdu::WriteSingleCoil); + } + + /// + /// \brief address + /// \return + /// + quint16 address() const { + return makeWord(_data[1], _data[0], ByteOrder::LittleEndian); + } + + /// + /// \brief value + /// \return + /// + quint16 value() const { + return makeWord(_data[3], _data[2], ByteOrder::LittleEndian); + } +}; + +#endif // WRITESINGLECOIL_H diff --git a/omodscan/modbusmessages/writesingleregister.h b/omodscan/modbusmessages/writesingleregister.h new file mode 100644 index 0000000..a2b73c8 --- /dev/null +++ b/omodscan/modbusmessages/writesingleregister.h @@ -0,0 +1,76 @@ +#ifndef WRITESINGLEREGISTER_H +#define WRITESINGLEREGISTER_H + +#include "modbusmessage.h" + +/// +/// \brief The WriteSingleRegisterRequest class +/// +class WriteSingleRegisterRequest : public ModbusMessage +{ +public: + /// + /// \brief WriteSingleRegisterRequest + /// \param pdu + /// \param timestamp + /// \param deviceId + /// + WriteSingleRegisterRequest(const QModbusPdu& pdu, const QDateTime& timestamp, int deviceId) + : ModbusMessage(pdu, timestamp, deviceId, true) + { + Q_ASSERT((_funcCode & ~QModbusPdu::ExceptionByte) == QModbusPdu::WriteSingleRegister); + } + + /// + /// \brief address + /// \return + /// + quint16 address() const { + return makeWord(_data[1], _data[0], ByteOrder::LittleEndian); + } + + /// + /// \brief value + /// \return + /// + quint16 value() const { + return makeWord(_data[3], _data[2], ByteOrder::LittleEndian); + } +}; + +/// +/// \brief The WriteSingleRegisterResponse class +/// +class WriteSingleRegisterResponse : public ModbusMessage +{ +public: + /// + /// \brief WriteSingleRegisterResponse + /// \param pdu + /// \param timestamp + /// \param deviceId + /// + WriteSingleRegisterResponse(const QModbusPdu& pdu, const QDateTime& timestamp, int deviceId) + :ModbusMessage(pdu, timestamp, deviceId, false) + { + Q_ASSERT((_funcCode & ~QModbusPdu::ExceptionByte) == QModbusPdu::WriteSingleRegister); + } + + /// + /// \brief address + /// \return + /// + quint16 address() const { + return makeWord(_data[1], _data[0], ByteOrder::LittleEndian); + } + + /// + /// \brief value + /// \return + /// + quint16 value() const { + return makeWord(_data[3], _data[2], ByteOrder::LittleEndian); + } +}; + +#endif // WRITESINGLEREGISTER_H diff --git a/omodscan/omodscan.pro b/omodscan/omodscan.pro index f529b9b..11f3334 100644 --- a/omodscan/omodscan.pro +++ b/omodscan/omodscan.pro @@ -21,7 +21,7 @@ win32:RC_ICONS += res/omodscan.ico INCLUDEPATH += controls \ dialogs \ - modbusinfo \ + modbusmessages \ SOURCES += \ controls/booleancombobox.cpp \ @@ -69,7 +69,7 @@ SOURCES += \ mainwindow.cpp \ modbusclient.cpp \ modbusdataunit.cpp \ - modbusinfo/modbuspduinfo.cpp \ + modbusmessages/modbusmessage.cpp \ modbusrtuscanner.cpp \ modbusscanner.cpp \ modbustcpscanner.cpp \ @@ -127,13 +127,25 @@ HEADERS += \ formmodsca.h \ htmldelegate.h \ mainwindow.h \ - modbusinfo/modbuspduinfo.h \ modbusclient.h \ modbusdataunit.h \ modbusexception.h \ modbusfunction.h \ - modbusinfo/readcoils.h \ + modbusmessages/diagnostics.h \ + modbusmessages/getcommeventcounter.h \ + modbusmessages/getcommeventlog.h \ + modbusmessages/modbusmessage.h \ + modbusmessages/modbusmessages.h \ + modbusmessages/readcoils.h \ modbuslimits.h \ + modbusmessages/readdiscreteinputs.h \ + modbusmessages/readexceptionstatus.h \ + modbusmessages/readholdingregisters.h \ + modbusmessages/readinputregisters.h \ + modbusmessages/writemultiplecoils.h \ + modbusmessages/writemultipleregisters.h \ + modbusmessages/writesinglecoil.h \ + modbusmessages/writesingleregister.h \ modbusrtuscanner.h \ modbusscanner.h \ modbussimulationparams.h \ From bf802811a66db25248cb72393e1d21ab260167fa Mon Sep 17 00:00:00 2001 From: sanny32 Date: Wed, 27 Sep 2023 17:21:03 +0300 Subject: [PATCH 08/90] Developing new log view --- omodscan/controls/outputwidget.cpp | 72 ++++++++++++ omodscan/modbusmessages/maskwriteregister.h | 92 +++++++++++++++ omodscan/modbusmessages/modbusmessage.cpp | 24 ++++ omodscan/modbusmessages/modbusmessages.h | 6 + omodscan/modbusmessages/readfifoqueue.h | 76 ++++++++++++ omodscan/modbusmessages/readfilerecord.h | 76 ++++++++++++ .../readwritemultipleregisters.h | 108 ++++++++++++++++++ omodscan/modbusmessages/reportserverid.h | 60 ++++++++++ omodscan/modbusmessages/writefilerecord.h | 76 ++++++++++++ omodscan/omodscan.pro | 6 + 10 files changed, 596 insertions(+) create mode 100644 omodscan/modbusmessages/maskwriteregister.h create mode 100644 omodscan/modbusmessages/readfifoqueue.h create mode 100644 omodscan/modbusmessages/readfilerecord.h create mode 100644 omodscan/modbusmessages/readwritemultipleregisters.h create mode 100644 omodscan/modbusmessages/reportserverid.h create mode 100644 omodscan/modbusmessages/writefilerecord.h diff --git a/omodscan/controls/outputwidget.cpp b/omodscan/controls/outputwidget.cpp index 16b9fa9..af6953c 100644 --- a/omodscan/controls/outputwidget.cpp +++ b/omodscan/controls/outputwidget.cpp @@ -1114,21 +1114,93 @@ void OutputWidget::showTrafficInfo(const QModelIndex& index) break; case QModbusPdu::ReportServerId: + if(!data->isRequest()) + { + auto resp = reinterpret_cast(data); + ui->trafficInfo->addItem(tr("Byte Count: %1").arg(formatByteValue(dataDisplayMode(), resp->byteCount()))); + ui->trafficInfo->addItem(tr("Data: %1").arg(formatByteArray(dataDisplayMode(), resp->data()))); + } break; case QModbusPdu::ReadFileRecord: + if(data->isRequest()) + { + auto req = reinterpret_cast(data); + ui->trafficInfo->addItem(tr("Byte Count: %1").arg(formatByteValue(dataDisplayMode(), req->byteCount()))); + ui->trafficInfo->addItem(tr("Data: %1").arg(formatByteArray(dataDisplayMode(), req->data()))); + } + else + { + auto resp = reinterpret_cast(data); + ui->trafficInfo->addItem(tr("Byte Count: %1").arg(formatByteValue(dataDisplayMode(), resp->byteCount()))); + ui->trafficInfo->addItem(tr("Data: %1").arg(formatByteArray(dataDisplayMode(), resp->data()))); + } break; case QModbusPdu::WriteFileRecord: + if(data->isRequest()) + { + auto req = reinterpret_cast(data); + ui->trafficInfo->addItem(tr("Request Data Length: %1").arg(formatByteValue(dataDisplayMode(), req->length()))); + ui->trafficInfo->addItem(tr("Data: %1").arg(formatByteArray(dataDisplayMode(), req->data()))); + } + else + { + auto resp = reinterpret_cast(data); + ui->trafficInfo->addItem(tr("Request Data Length: %1").arg(formatByteValue(dataDisplayMode(), resp->length()))); + ui->trafficInfo->addItem(tr("Data: %1").arg(formatByteArray(dataDisplayMode(), resp->data()))); + } break; case QModbusPdu::MaskWriteRegister: + if(data->isRequest()) + { + auto req = reinterpret_cast(data); + ui->trafficInfo->addItem(tr("Address: %1").arg(formatWordValue(dataDisplayMode(), req->address()))); + ui->trafficInfo->addItem(tr("And Mask: %1").arg(formatWordValue(dataDisplayMode(), req->andMask()))); + ui->trafficInfo->addItem(tr("Or Mask: %1").arg(formatWordValue(dataDisplayMode(), req->orMask()))); + } + else + { + auto resp = reinterpret_cast(data); + ui->trafficInfo->addItem(tr("Address: %1").arg(formatWordValue(dataDisplayMode(), resp->address()))); + ui->trafficInfo->addItem(tr("And Mask: %1").arg(formatWordValue(dataDisplayMode(), resp->andMask()))); + ui->trafficInfo->addItem(tr("Or Mask: %1").arg(formatWordValue(dataDisplayMode(), resp->orMask()))); + } break; case QModbusPdu::ReadWriteMultipleRegisters: + if(data->isRequest()) + { + auto req = reinterpret_cast(data); + ui->trafficInfo->addItem(tr("Read Starting Address: %1").arg(formatWordValue(dataDisplayMode(), req->readStartAddress()))); + ui->trafficInfo->addItem(tr("Quantity to Read: %1").arg(formatWordValue(dataDisplayMode(), req->readLength()))); + ui->trafficInfo->addItem(tr("Write Starting Address: %1").arg(formatWordValue(dataDisplayMode(), req->writeStartAddress()))); + ui->trafficInfo->addItem(tr("Quantity to Write: %1").arg(formatWordValue(dataDisplayMode(), req->writeLength()))); + ui->trafficInfo->addItem(tr("Write Byte Count: %1").arg(formatByteValue(dataDisplayMode(), req->writeByteCount()))); + ui->trafficInfo->addItem(tr("Write Registers Value: %1").arg(formatByteArray(dataDisplayMode(), req->writeValues()))); + } + else + { + auto resp = reinterpret_cast(data); + ui->trafficInfo->addItem(tr("Byte Count: %1").arg(formatByteValue(dataDisplayMode(), resp->byteCount()))); + ui->trafficInfo->addItem(tr("Registers Value: %1").arg(formatByteArray(dataDisplayMode(), resp->values()))); + } break; case QModbusPdu::ReadFifoQueue: + if(data->isRequest()) + { + auto req = reinterpret_cast(data); + ui->trafficInfo->addItem(tr("FIFO Point Address: %1").arg(formatWordValue(dataDisplayMode(), req->fifoAddress()))); + } + else + { + auto resp = reinterpret_cast(data); + ui->trafficInfo->addItem(tr("Byte Count: %1").arg(formatByteValue(dataDisplayMode(), resp->byteCount()))); + ui->trafficInfo->addItem(tr("FIFO Count: %1").arg(formatByteValue(dataDisplayMode(), resp->fifoCount()))); + ui->trafficInfo->addItem(tr("FIFO Value Register: %1").arg(formatByteArray(dataDisplayMode(), resp->fifoValue()))); + } break; default: diff --git a/omodscan/modbusmessages/maskwriteregister.h b/omodscan/modbusmessages/maskwriteregister.h new file mode 100644 index 0000000..5ec2a4b --- /dev/null +++ b/omodscan/modbusmessages/maskwriteregister.h @@ -0,0 +1,92 @@ +#ifndef MASKWRITEREGISTER_H +#define MASKWRITEREGISTER_H + +#include "modbusmessage.h" + +/// +/// \brief The MaskWriteRegisterRequest class +/// +class MaskWriteRegisterRequest : public ModbusMessage +{ +public: + /// + /// \brief MaskWriteRegisterRequest + /// \param pdu + /// \param timestamp + /// \param deviceId + /// + MaskWriteRegisterRequest(const QModbusPdu& pdu, const QDateTime& timestamp, int deviceId) + : ModbusMessage(pdu, timestamp, deviceId, true) + { + Q_ASSERT((_funcCode & ~QModbusPdu::ExceptionByte) == QModbusPdu::MaskWriteRegister); + } + + /// + /// \brief address + /// \return + /// + quint16 address() const { + return makeWord(_data[1], _data[0], ByteOrder::LittleEndian); + } + + /// + /// \brief andMask + /// \return + /// + quint16 andMask() const { + return makeWord(_data[3], _data[2], ByteOrder::LittleEndian); + } + + /// + /// \brief orMask + /// \return + /// + quint16 orMask() const { + return makeWord(_data[5], _data[4], ByteOrder::LittleEndian); + } +}; + +/// +/// \brief The MaskWriteRegisterResponse class +/// +class MaskWriteRegisterResponse : public ModbusMessage +{ +public: + /// + /// \brief MaskWriteRegisterResponse + /// \param pdu + /// \param timestamp + /// \param deviceId + /// + MaskWriteRegisterResponse(const QModbusPdu& pdu, const QDateTime& timestamp, int deviceId) + :ModbusMessage(pdu, timestamp, deviceId, false) + { + Q_ASSERT((_funcCode & ~QModbusPdu::ExceptionByte) == QModbusPdu::MaskWriteRegister); + } + + /// + /// \brief address + /// \return + /// + quint16 address() const { + return makeWord(_data[1], _data[0], ByteOrder::LittleEndian); + } + + /// + /// \brief andMask + /// \return + /// + quint16 andMask() const { + return makeWord(_data[3], _data[2], ByteOrder::LittleEndian); + } + + /// + /// \brief orMask + /// \return + /// + quint16 orMask() const { + return makeWord(_data[5], _data[4], ByteOrder::LittleEndian); + } +}; + +#endif // MASKWRITEREGISTER_H diff --git a/omodscan/modbusmessages/modbusmessage.cpp b/omodscan/modbusmessages/modbusmessage.cpp index 1096373..6fbc5d0 100644 --- a/omodscan/modbusmessages/modbusmessage.cpp +++ b/omodscan/modbusmessages/modbusmessage.cpp @@ -60,6 +60,30 @@ const ModbusMessage* ModbusMessage::create(const QModbusPdu& pdu, const QDateTim if(request) return new WriteMultipleRegistersRequest(pdu, timestamp, deviceId); else return new WriteMultipleRegistersResponse(pdu, timestamp, deviceId); + case QModbusPdu::ReportServerId: + if(request) return new ReportServerIdRequest(pdu, timestamp, deviceId); + else return new ReportServerIdResponse(pdu, timestamp, deviceId); + + case QModbusPdu::ReadFileRecord: + if(request) return new ReadFileRecordRequest(pdu, timestamp, deviceId); + else return new ReadFileRecordResponse(pdu, timestamp, deviceId); + + case QModbusPdu::WriteFileRecord: + if(request) return new WriteFileRecordRequest(pdu, timestamp, deviceId); + else return new WriteFileRecordResponse(pdu, timestamp, deviceId); + + case QModbusPdu::MaskWriteRegister: + if(request) return new MaskWriteRegisterRequest(pdu, timestamp, deviceId); + else return new MaskWriteRegisterResponse(pdu, timestamp, deviceId); + + case QModbusPdu::ReadWriteMultipleRegisters: + if(request) return new ReadWriteMultipleRegistersRequest(pdu, timestamp, deviceId); + else return new ReadWriteMultipleRegistersResponse(pdu, timestamp, deviceId); + + case QModbusPdu::ReadFifoQueue: + if(request) return new ReadFifoQueueRequest(pdu, timestamp, deviceId); + else return new ReadFifoQueueResponse(pdu, timestamp, deviceId); + default: return nullptr; } diff --git a/omodscan/modbusmessages/modbusmessages.h b/omodscan/modbusmessages/modbusmessages.h index 4e42604..7d8d2bf 100644 --- a/omodscan/modbusmessages/modbusmessages.h +++ b/omodscan/modbusmessages/modbusmessages.h @@ -11,3 +11,9 @@ #include "getcommeventlog.h" #include "writemultiplecoils.h" #include "writemultipleregisters.h" +#include "reportserverid.h" +#include "readfilerecord.h" +#include "writefilerecord.h" +#include "maskwriteregister.h" +#include "readwritemultipleregisters.h" +#include "readfifoqueue.h" diff --git a/omodscan/modbusmessages/readfifoqueue.h b/omodscan/modbusmessages/readfifoqueue.h new file mode 100644 index 0000000..31afff8 --- /dev/null +++ b/omodscan/modbusmessages/readfifoqueue.h @@ -0,0 +1,76 @@ +#ifndef READFIFOQUEUE_H +#define READFIFOQUEUE_H + +#include "modbusmessage.h" + +/// +/// \brief The ReadFifoQueueRequest class +/// +class ReadFifoQueueRequest : public ModbusMessage +{ +public: + /// + /// \brief ReadFifoQueueRequest + /// \param pdu + /// \param timestamp + /// \param deviceId + /// + ReadFifoQueueRequest(const QModbusPdu& pdu, const QDateTime& timestamp, int deviceId) + : ModbusMessage(pdu, timestamp, deviceId, true) + { + Q_ASSERT((_funcCode & ~QModbusPdu::ExceptionByte) == QModbusPdu::ReadFifoQueue); + } + + /// + /// \brief fifoAddress + /// \return + /// + quint16 fifoAddress() const { + return makeWord(_data[1], _data[0], ByteOrder::LittleEndian); + } +}; + +/// +/// \brief The ReadFifoQueueResponse class +/// +class ReadFifoQueueResponse : public ModbusMessage +{ +public: + /// + /// \brief ReadFifoQueueResponse + /// \param pdu + /// \param timestamp + /// \param deviceId + /// + ReadFifoQueueResponse(const QModbusPdu& pdu, const QDateTime& timestamp, int deviceId) + :ModbusMessage(pdu, timestamp, deviceId, false) + { + Q_ASSERT((_funcCode & ~QModbusPdu::ExceptionByte) == QModbusPdu::ReadFifoQueue); + } + + /// + /// \brief byteCount + /// \return + /// + quint16 byteCount() const { + return makeWord(_data[1], _data[0], ByteOrder::LittleEndian); + } + + /// + /// \brief fifoCount + /// \return + /// + quint16 fifoCount() const { + return makeWord(_data[3], _data[2], ByteOrder::LittleEndian); + } + + /// + /// \brief fifoValue + /// \return + /// + QByteArray fifoValue() const { + return _data.right(_data.size() - 4); + } +}; + +#endif // READFIFOQUEUE_H diff --git a/omodscan/modbusmessages/readfilerecord.h b/omodscan/modbusmessages/readfilerecord.h new file mode 100644 index 0000000..4f57aa4 --- /dev/null +++ b/omodscan/modbusmessages/readfilerecord.h @@ -0,0 +1,76 @@ +#ifndef READFILERECORD_H +#define READFILERECORD_H + +#include "modbusmessage.h" + +/// +/// \brief The ReadFileRecordRequest class +/// +class ReadFileRecordRequest : public ModbusMessage +{ +public: + /// + /// \brief ReadFileRecordRequest + /// \param pdu + /// \param timestamp + /// \param deviceId + /// + ReadFileRecordRequest(const QModbusPdu& pdu, const QDateTime& timestamp, int deviceId) + : ModbusMessage(pdu, timestamp, deviceId, true) + { + Q_ASSERT((_funcCode & ~QModbusPdu::ExceptionByte) == QModbusPdu::ReadFileRecord); + } + + /// + /// \brief byteCount + /// \return + /// + quint8 byteCount() const { + return _data[0]; + } + + /// + /// \brief data + /// \return + /// + QByteArray data() const { + return _data.right(_data.size() - 1); + } +}; + +/// +/// \brief The ReadFileRecordResponse class +/// +class ReadFileRecordResponse : public ModbusMessage +{ +public: + /// + /// \brief ReadFileRecordResponse + /// \param pdu + /// \param timestamp + /// \param deviceId + /// + ReadFileRecordResponse(const QModbusPdu& pdu, const QDateTime& timestamp, int deviceId) + :ModbusMessage(pdu, timestamp, deviceId, false) + { + Q_ASSERT((_funcCode & ~QModbusPdu::ExceptionByte) == QModbusPdu::ReadFileRecord); + } + + /// + /// \brief byteCount + /// \return + /// + quint8 byteCount() const { + return _data[0]; + } + + /// + /// \brief data + /// \return + /// + QByteArray data() const { + return _data.right(_data.size() - 1); + } +}; + +#endif // READFILERECORD_H diff --git a/omodscan/modbusmessages/readwritemultipleregisters.h b/omodscan/modbusmessages/readwritemultipleregisters.h new file mode 100644 index 0000000..6f756a6 --- /dev/null +++ b/omodscan/modbusmessages/readwritemultipleregisters.h @@ -0,0 +1,108 @@ +#ifndef READWRITEMULTIPLEREGISTERS_H +#define READWRITEMULTIPLEREGISTERS_H + +#include "modbusmessage.h" + +/// +/// \brief The ReadWriteMultipleRegistersRequest class +/// +class ReadWriteMultipleRegistersRequest : public ModbusMessage +{ +public: + /// + /// \brief ReadWriteMultipleRegistersRequest + /// \param pdu + /// \param timestamp + /// \param deviceId + /// + ReadWriteMultipleRegistersRequest(const QModbusPdu& pdu, const QDateTime& timestamp, int deviceId) + : ModbusMessage(pdu, timestamp, deviceId, true) + { + Q_ASSERT((_funcCode & ~QModbusPdu::ExceptionByte) == QModbusPdu::ReadWriteMultipleRegisters); + } + + /// + /// \brief readStartAddress + /// \return + /// + quint16 readStartAddress() const { + return makeWord(_data[1], _data[0], ByteOrder::LittleEndian); + } + + /// + /// \brief readLength + /// \return + /// + quint16 readLength() const { + return makeWord(_data[3], _data[2], ByteOrder::LittleEndian); + } + + /// + /// \brief writeStartAddress + /// \return + /// + quint16 writeStartAddress() const { + return makeWord(_data[5], _data[4], ByteOrder::LittleEndian); + } + + /// + /// \brief writeLength + /// \return + /// + quint16 writeLength() const { + return makeWord(_data[7], _data[6], ByteOrder::LittleEndian); + } + + /// + /// \brief writeByteCount + /// \return + /// + quint8 writeByteCount() const { + return _data[8]; + } + + /// + /// \brief writeValues + /// \return + /// + QByteArray writeValues() const { + return _data.right(_data.size() - 9); + } +}; + +/// +/// \brief The ReadWriteMultipleRegistersResponse class +/// +class ReadWriteMultipleRegistersResponse : public ModbusMessage +{ +public: + /// + /// \brief ReadWriteMultipleRegistersResponse + /// \param pdu + /// \param timestamp + /// \param deviceId + /// + ReadWriteMultipleRegistersResponse(const QModbusPdu& pdu, const QDateTime& timestamp, int deviceId) + :ModbusMessage(pdu, timestamp, deviceId, false) + { + Q_ASSERT((_funcCode & ~QModbusPdu::ExceptionByte) == QModbusPdu::ReadWriteMultipleRegisters); + } + + /// + /// \brief byteCount + /// \return + /// + quint8 byteCount() const { + return _data[0]; + } + + /// + /// \brief values + /// \return + /// + QByteArray values() const { + return _data.right(_data.size() - 1); + } +}; + +#endif // READWRITEMULTIPLEREGISTERS_H diff --git a/omodscan/modbusmessages/reportserverid.h b/omodscan/modbusmessages/reportserverid.h new file mode 100644 index 0000000..56cfd72 --- /dev/null +++ b/omodscan/modbusmessages/reportserverid.h @@ -0,0 +1,60 @@ +#ifndef REPORTSERVERID_H +#define REPORTSERVERID_H + +#include "modbusmessage.h" + +/// +/// \brief The ReportServerIdRequest class +/// +class ReportServerIdRequest : public ModbusMessage +{ +public: + /// + /// \brief ReportServerIdRequest + /// \param pdu + /// \param timestamp + /// \param deviceId + /// + ReportServerIdRequest(const QModbusPdu& pdu, const QDateTime& timestamp, int deviceId) + : ModbusMessage(pdu, timestamp, deviceId, true) + { + Q_ASSERT((_funcCode & ~QModbusPdu::ExceptionByte) == QModbusPdu::ReportServerId); + } +}; + +/// +/// \brief The ReportServerIdResponse class +/// +class ReportServerIdResponse : public ModbusMessage +{ +public: + /// + /// \brief ReportServerIdResponse + /// \param pdu + /// \param timestamp + /// \param deviceId + /// + ReportServerIdResponse(const QModbusPdu& pdu, const QDateTime& timestamp, int deviceId) + :ModbusMessage(pdu, timestamp, deviceId, false) + { + Q_ASSERT((_funcCode & ~QModbusPdu::ExceptionByte) == QModbusPdu::ReportServerId); + } + + /// + /// \brief byteCount + /// \return + /// + quint8 byteCount() const { + return _data[0]; + } + + /// + /// \brief data + /// \return + /// + QByteArray data() const { + return _data.right(_data.size() - 1); + } +}; + +#endif // REPORTSERVERID_H diff --git a/omodscan/modbusmessages/writefilerecord.h b/omodscan/modbusmessages/writefilerecord.h new file mode 100644 index 0000000..f8e7b70 --- /dev/null +++ b/omodscan/modbusmessages/writefilerecord.h @@ -0,0 +1,76 @@ +#ifndef WRITEFILERECORD_H +#define WRITEFILERECORD_H + +#include "modbusmessage.h" + +/// +/// \brief The WriteFileRecordRequest class +/// +class WriteFileRecordRequest : public ModbusMessage +{ +public: + /// + /// \brief WriteFileRecordRequest + /// \param pdu + /// \param timestamp + /// \param deviceId + /// + WriteFileRecordRequest(const QModbusPdu& pdu, const QDateTime& timestamp, int deviceId) + : ModbusMessage(pdu, timestamp, deviceId, true) + { + Q_ASSERT((_funcCode & ~QModbusPdu::ExceptionByte) == QModbusPdu::WriteFileRecord); + } + + /// + /// \brief length + /// \return + /// + quint8 length() const { + return _data[0]; + } + + /// + /// \brief data + /// \return + /// + QByteArray data() const { + return _data.right(_data.size() - 1); + } +}; + +/// +/// \brief The WriteFileRecordResponse class +/// +class WriteFileRecordResponse : public ModbusMessage +{ +public: + /// + /// \brief WriteFileRecordResponse + /// \param pdu + /// \param timestamp + /// \param deviceId + /// + WriteFileRecordResponse(const QModbusPdu& pdu, const QDateTime& timestamp, int deviceId) + :ModbusMessage(pdu, timestamp, deviceId, false) + { + Q_ASSERT((_funcCode & ~QModbusPdu::ExceptionByte) == QModbusPdu::WriteFileRecord); + } + + /// + /// \brief length + /// \return + /// + quint8 length() const { + return _data[0]; + } + + /// + /// \brief data + /// \return + /// + QByteArray data() const { + return _data.right(_data.size() - 1); + } +}; + +#endif // WRITEFILERECORD_H diff --git a/omodscan/omodscan.pro b/omodscan/omodscan.pro index 11f3334..17e9222 100644 --- a/omodscan/omodscan.pro +++ b/omodscan/omodscan.pro @@ -134,14 +134,20 @@ HEADERS += \ modbusmessages/diagnostics.h \ modbusmessages/getcommeventcounter.h \ modbusmessages/getcommeventlog.h \ + modbusmessages/maskwriteregister.h \ modbusmessages/modbusmessage.h \ modbusmessages/modbusmessages.h \ modbusmessages/readcoils.h \ modbuslimits.h \ modbusmessages/readdiscreteinputs.h \ modbusmessages/readexceptionstatus.h \ + modbusmessages/readfifoqueue.h \ + modbusmessages/readfilerecord.h \ modbusmessages/readholdingregisters.h \ modbusmessages/readinputregisters.h \ + modbusmessages/readwritemultipleregisters.h \ + modbusmessages/reportserverid.h \ + modbusmessages/writefilerecord.h \ modbusmessages/writemultiplecoils.h \ modbusmessages/writemultipleregisters.h \ modbusmessages/writesinglecoil.h \ From a182d838db7b112588b47ce69c7d674e349a8774 Mon Sep 17 00:00:00 2001 From: sanny32 Date: Thu, 28 Sep 2023 08:26:43 +0300 Subject: [PATCH 09/90] Developing new log view --- omodscan/controls/modbusmessagewidget.cpp | 351 ++++++++++++++++++++++ omodscan/controls/modbusmessagewidget.h | 32 ++ omodscan/controls/outputwidget.cpp | 306 +------------------ omodscan/controls/outputwidget.ui | 9 +- omodscan/formatutils.h | 4 +- omodscan/modbusmessages/modbusmessage.h | 14 +- omodscan/omodscan.pro | 2 + 7 files changed, 415 insertions(+), 303 deletions(-) create mode 100644 omodscan/controls/modbusmessagewidget.cpp create mode 100644 omodscan/controls/modbusmessagewidget.h diff --git a/omodscan/controls/modbusmessagewidget.cpp b/omodscan/controls/modbusmessagewidget.cpp new file mode 100644 index 0000000..c4f7b2f --- /dev/null +++ b/omodscan/controls/modbusmessagewidget.cpp @@ -0,0 +1,351 @@ +#include "formatutils.h" +#include "modbusmessagewidget.h" +#include "modbusmessages.h" + +/// +/// \brief ModbusMessageWidget::ModbusMessageWidget +/// \param parent +/// +ModbusMessageWidget::ModbusMessageWidget(QWidget *parent) + : QListWidget(parent) + ,_msg(nullptr) +{ +} + +/// +/// \brief ModbusMessageWidget::clear +/// +void ModbusMessageWidget::clear() +{ + _msg = nullptr; + update(); +} + +/// +/// \brief ModbusMessageWidget::dataDisplayMode +/// \return +/// +DataDisplayMode ModbusMessageWidget::dataDisplayMode() const +{ + return _dataDisplayMode; +} + +/// +/// \brief ModbusMessageWidget::setDataDisplayMode +/// \param mode +/// +void ModbusMessageWidget::setDataDisplayMode(DataDisplayMode mode) +{ + _dataDisplayMode = mode; + update(); +} + +/// +/// \brief ModbusMessageWidget::modbusMessage +/// \return +/// +const ModbusMessage* ModbusMessageWidget::modbusMessage() const +{ + return _msg; +} + +/// +/// \brief ModbusMessageWidget::setModbusMessage +/// \param msg +/// +void ModbusMessageWidget::setModbusMessage(const ModbusMessage* msg) +{ + _msg = msg; + update(); +} + +/// +/// \brief ModbusMessageWidget::update +/// +void ModbusMessageWidget::update() +{ + QListWidget::clear(); + if(_msg == nullptr) + return; + + const auto function = QString("%1 (%2)").arg(formatByteValue(_dataDisplayMode, _msg->function()), _msg->function()); + + addItem(tr("Type: %1").arg(_msg->isRequest() ? tr("Tx Message") : tr("Rx Message"))); + addItem(tr("Timestamp: %1").arg(_msg->timestamp().toString(Qt::ISODateWithMs))); + addItem(tr("Device ID: %1").arg(formatByteValue(_dataDisplayMode, _msg->deviceId()))); + + if(_msg->isException()) + { + const auto exception = QString("%1 (%2)").arg(formatByteValue(_dataDisplayMode, _msg->exception()), _msg->exception()); + addItem(tr("Error Code: %1").arg(formatByteValue(_dataDisplayMode, _msg->function()))); + addItem(tr("Exception Code: %1").arg(exception)); + return; + } + + addItem(tr("Function Code: %1").arg(function)); + + switch(_msg->function()) + { + case QModbusPdu::ReadCoils: + if(_msg->isRequest()) + { + auto req = reinterpret_cast(_msg); + addItem(tr("Start Address: %1").arg(formatWordValue(_dataDisplayMode, req->startAddress()))); + addItem(tr("Length: %1").arg(formatWordValue(_dataDisplayMode, req->length()))); + } + else + { + auto resp = reinterpret_cast(_msg); + addItem(tr("Byte Count: %1").arg(formatByteValue(_dataDisplayMode, resp->byteCount()))); + addItem(tr("Coil Status: %1").arg(formatByteArray(_dataDisplayMode, resp->coilStatus()))); + } + break; + + case QModbusPdu::ReadDiscreteInputs: + if(_msg->isRequest()) + { + auto req = reinterpret_cast(_msg); + addItem(tr("Start Address: %1").arg(formatWordValue(_dataDisplayMode, req->startAddress()))); + addItem(tr("Length: %1").arg(formatWordValue(_dataDisplayMode, req->length()))); + } + else + { + auto resp = reinterpret_cast(_msg); + addItem(tr("Byte Count: %1").arg(formatByteValue(_dataDisplayMode, resp->byteCount()))); + addItem(tr("Input Status: %1").arg(formatByteArray(_dataDisplayMode, resp->inputStatus()))); + } + break; + + case QModbusPdu::ReadHoldingRegisters: + if(_msg->isRequest()) + { + auto req = reinterpret_cast(_msg); + addItem(tr("Start Address: %1").arg(formatWordValue(_dataDisplayMode, req->startAddress()))); + addItem(tr("Length: %1").arg(formatWordValue(_dataDisplayMode, req->length()))); + } + else + { + auto resp = reinterpret_cast(_msg); + addItem(tr("Byte Count: %1").arg(formatByteValue(_dataDisplayMode, resp->byteCount()))); + addItem(tr("Register Value: %1").arg(formatByteArray(_dataDisplayMode, resp->registerValue()))); + } + break; + + case QModbusPdu::ReadInputRegisters: + if(_msg->isRequest()) + { + auto req = reinterpret_cast(_msg); + addItem(tr("Start Address: %1").arg(formatWordValue(_dataDisplayMode, req->startAddress()))); + addItem(tr("Length: %1").arg(formatWordValue(_dataDisplayMode, req->length()))); + } + else + { + auto resp = reinterpret_cast(_msg); + addItem(tr("Byte Count: %1").arg(formatByteValue(_dataDisplayMode, resp->byteCount()))); + addItem(tr("Input Registers: %1").arg(formatByteArray(_dataDisplayMode, resp->registerValue()))); + } + break; + + case QModbusPdu::WriteSingleCoil: + if(_msg->isRequest()) + { + auto req = reinterpret_cast(_msg); + addItem(tr("Output Address: %1").arg(formatWordValue(_dataDisplayMode, req->address()))); + addItem(tr("Output Value: %1").arg(formatWordValue(_dataDisplayMode, req->value()))); + } + else + { + auto resp = reinterpret_cast(_msg); + addItem(tr("Output Address: %1").arg(formatWordValue(_dataDisplayMode, resp->address()))); + addItem(tr("Output Value: %1").arg(formatWordValue(_dataDisplayMode, resp->value()))); + } + break; + + case QModbusPdu::WriteSingleRegister: + if(_msg->isRequest()) + { + auto req = reinterpret_cast(_msg); + addItem(tr("Register Address: %1").arg(formatWordValue(_dataDisplayMode, req->address()))); + addItem(tr("Register Value: %1").arg(formatWordValue(_dataDisplayMode, req->value()))); + } + else + { + auto resp = reinterpret_cast(_msg); + addItem(tr("Register Address: %1").arg(formatWordValue(_dataDisplayMode, resp->address()))); + addItem(tr("Register Value: %1").arg(formatWordValue(_dataDisplayMode, resp->value()))); + } + break; + + case QModbusPdu::ReadExceptionStatus: + if(!_msg->isRequest()) + { + auto resp = reinterpret_cast(_msg); + addItem(tr("Output Data: %1").arg(formatByteValue(_dataDisplayMode, resp->outputData()))); + } + break; + + case QModbusPdu::Diagnostics: + if(_msg->isRequest()) + { + auto req = reinterpret_cast(_msg); + addItem(tr("Sub-function: %1").arg(formatWordValue(_dataDisplayMode, req->subfunc()))); + addItem(tr("Data: %1").arg(formatByteArray(_dataDisplayMode, req->data()))); + } + else + { + auto resp = reinterpret_cast(_msg); + addItem(tr("Sub-function: %1").arg(formatWordValue(_dataDisplayMode, resp->subfunc()))); + addItem(tr("Data: %1").arg(formatByteArray(_dataDisplayMode, resp->data()))); + } + break; + + case QModbusPdu::GetCommEventCounter: + if(!_msg->isRequest()) + { + auto resp = reinterpret_cast(_msg); + addItem(tr("Status: %1").arg(formatWordValue(_dataDisplayMode, resp->status()))); + addItem(tr("Event Count: %1").arg(formatWordValue(_dataDisplayMode, resp->eventCount()))); + } + break; + + case QModbusPdu::GetCommEventLog: + if(!_msg->isRequest()) + { + auto resp = reinterpret_cast(_msg); + addItem(tr("Byte Count: %1").arg(formatByteValue(_dataDisplayMode, resp->byteCount()))); + addItem(tr("Status: %1").arg(formatWordValue(_dataDisplayMode, resp->status()))); + addItem(tr("Event Count: %1").arg(formatWordValue(_dataDisplayMode, resp->eventCount()))); + addItem(tr("Message Count: %1").arg(formatWordValue(_dataDisplayMode, resp->messageCount()))); + addItem(tr("Events: %1").arg(formatByteArray(_dataDisplayMode, resp->events()))); + } + break; + + case QModbusPdu::WriteMultipleCoils: + if(_msg->isRequest()) + { + auto req = reinterpret_cast(_msg); + addItem(tr("Starting Address: %1").arg(formatWordValue(_dataDisplayMode, req->startAddress()))); + addItem(tr("Quantity of Outputs: %1").arg(formatWordValue(_dataDisplayMode, req->quantity()))); + addItem(tr("Byte Count: %1").arg(formatByteValue(_dataDisplayMode, req->byteCount()))); + addItem(tr("Output Value: %1").arg(formatByteArray(_dataDisplayMode, req->values()))); + } + else + { + auto resp = reinterpret_cast(_msg); + addItem(tr("Starting Address: %1").arg(formatWordValue(_dataDisplayMode, resp->startAddress()))); + addItem(tr("Quantity of Outputs: %1").arg(formatWordValue(_dataDisplayMode, resp->quantity()))); + } + break; + + case QModbusPdu::WriteMultipleRegisters: + if(_msg->isRequest()) + { + auto req = reinterpret_cast(_msg); + addItem(tr("Starting Address: %1").arg(formatWordValue(_dataDisplayMode, req->startAddress()))); + addItem(tr("Quantity of Registers: %1").arg(formatWordValue(_dataDisplayMode, req->quantity()))); + addItem(tr("Byte Count: %1").arg(formatByteValue(_dataDisplayMode, req->byteCount()))); + addItem(tr("Registers Value: %1").arg(formatByteArray(_dataDisplayMode, req->values()))); + } + else + { + auto resp = reinterpret_cast(_msg); + addItem(tr("Starting Address: %1").arg(formatWordValue(_dataDisplayMode, resp->startAddress()))); + addItem(tr("Quantity of Registers: %1").arg(formatWordValue(_dataDisplayMode, resp->quantity()))); + } + break; + + case QModbusPdu::ReportServerId: + if(!_msg->isRequest()) + { + auto resp = reinterpret_cast(_msg); + addItem(tr("Byte Count: %1").arg(formatByteValue(_dataDisplayMode, resp->byteCount()))); + addItem(tr("Data: %1").arg(formatByteArray(_dataDisplayMode, resp->data()))); + } + break; + + case QModbusPdu::ReadFileRecord: + if(_msg->isRequest()) + { + auto req = reinterpret_cast(_msg); + addItem(tr("Byte Count: %1").arg(formatByteValue(_dataDisplayMode, req->byteCount()))); + addItem(tr("Data: %1").arg(formatByteArray(_dataDisplayMode, req->data()))); + } + else + { + auto resp = reinterpret_cast(_msg); + addItem(tr("Byte Count: %1").arg(formatByteValue(_dataDisplayMode, resp->byteCount()))); + addItem(tr("Data: %1").arg(formatByteArray(_dataDisplayMode, resp->data()))); + } + break; + + case QModbusPdu::WriteFileRecord: + if(_msg->isRequest()) + { + auto req = reinterpret_cast(_msg); + addItem(tr("Request _msg Length: %1").arg(formatByteValue(_dataDisplayMode, req->length()))); + addItem(tr("Data: %1").arg(formatByteArray(_dataDisplayMode, req->data()))); + } + else + { + auto resp = reinterpret_cast(_msg); + addItem(tr("Request _msg Length: %1").arg(formatByteValue(_dataDisplayMode, resp->length()))); + addItem(tr("Data: %1").arg(formatByteArray(_dataDisplayMode, resp->data()))); + } + break; + + case QModbusPdu::MaskWriteRegister: + if(_msg->isRequest()) + { + auto req = reinterpret_cast(_msg); + addItem(tr("Address: %1").arg(formatWordValue(_dataDisplayMode, req->address()))); + addItem(tr("And Mask: %1").arg(formatWordValue(_dataDisplayMode, req->andMask()))); + addItem(tr("Or Mask: %1").arg(formatWordValue(_dataDisplayMode, req->orMask()))); + } + else + { + auto resp = reinterpret_cast(_msg); + addItem(tr("Address: %1").arg(formatWordValue(_dataDisplayMode, resp->address()))); + addItem(tr("And Mask: %1").arg(formatWordValue(_dataDisplayMode, resp->andMask()))); + addItem(tr("Or Mask: %1").arg(formatWordValue(_dataDisplayMode, resp->orMask()))); + } + break; + + case QModbusPdu::ReadWriteMultipleRegisters: + if(_msg->isRequest()) + { + auto req = reinterpret_cast(_msg); + addItem(tr("Read Starting Address: %1").arg(formatWordValue(_dataDisplayMode, req->readStartAddress()))); + addItem(tr("Quantity to Read: %1").arg(formatWordValue(_dataDisplayMode, req->readLength()))); + addItem(tr("Write Starting Address: %1").arg(formatWordValue(_dataDisplayMode, req->writeStartAddress()))); + addItem(tr("Quantity to Write: %1").arg(formatWordValue(_dataDisplayMode, req->writeLength()))); + addItem(tr("Write Byte Count: %1").arg(formatByteValue(_dataDisplayMode, req->writeByteCount()))); + addItem(tr("Write Registers Value: %1").arg(formatByteArray(_dataDisplayMode, req->writeValues()))); + } + else + { + auto resp = reinterpret_cast(_msg); + addItem(tr("Byte Count: %1").arg(formatByteValue(_dataDisplayMode, resp->byteCount()))); + addItem(tr("Registers Value: %1").arg(formatByteArray(_dataDisplayMode, resp->values()))); + } + break; + + case QModbusPdu::ReadFifoQueue: + if(_msg->isRequest()) + { + auto req = reinterpret_cast(_msg); + addItem(tr("FIFO Point Address: %1").arg(formatWordValue(_dataDisplayMode, req->fifoAddress()))); + } + else + { + auto resp = reinterpret_cast(_msg); + addItem(tr("Byte Count: %1").arg(formatByteValue(_dataDisplayMode, resp->byteCount()))); + addItem(tr("FIFO Count: %1").arg(formatByteValue(_dataDisplayMode, resp->fifoCount()))); + addItem(tr("FIFO Value Register: %1").arg(formatByteArray(_dataDisplayMode, resp->fifoValue()))); + } + break; + + default: + addItem(tr("Data: %1").arg(_msg->data(_dataDisplayMode))); + break; + } +} diff --git a/omodscan/controls/modbusmessagewidget.h b/omodscan/controls/modbusmessagewidget.h new file mode 100644 index 0000000..691b49c --- /dev/null +++ b/omodscan/controls/modbusmessagewidget.h @@ -0,0 +1,32 @@ +#ifndef MODBUSMESSAGEWIDGET_H +#define MODBUSMESSAGEWIDGET_H + +#include +#include "modbusmessage.h" + +/// +/// \brief The ModbusMessageWidget class +/// +class ModbusMessageWidget : public QListWidget +{ + Q_OBJECT +public: + explicit ModbusMessageWidget(QWidget *parent = nullptr); + + void clear(); + + DataDisplayMode dataDisplayMode() const; + void setDataDisplayMode(DataDisplayMode mode); + + const ModbusMessage* modbusMessage() const; + void setModbusMessage(const ModbusMessage* msg); + +private: + void update(); + +private: + DataDisplayMode _dataDisplayMode; + const ModbusMessage* _msg; +}; + +#endif // MODBUSMESSAGEWIDGET_H diff --git a/omodscan/controls/outputwidget.cpp b/omodscan/controls/outputwidget.cpp index af6953c..70882f9 100644 --- a/omodscan/controls/outputwidget.cpp +++ b/omodscan/controls/outputwidget.cpp @@ -409,13 +409,13 @@ OutputWidget::OutputWidget(QWidget *parent) : setUninitializedStatus(); ui->logView->setItemDelegate(new HtmlDelegate(this)); - ui->trafficInfo->setItemDelegate(new HtmlDelegate(this)); + ui->modbusMsg->setItemDelegate(new HtmlDelegate(this)); connect(ui->logView->selectionModel(), &QItemSelectionModel::selectionChanged, this, [&](const QItemSelection& sel) { if(sel.indexes().isEmpty()) - ui->trafficInfo->clear(); + ui->modbusMsg->clear(); else showTrafficInfo(sel.indexes().first()); }); @@ -606,7 +606,7 @@ void OutputWidget::setFont(const QFont& font) ui->listView->setFont(font); ui->labelStatus->setFont(font); ui->logView->setFont(font); - ui->trafficInfo->setFont(font); + ui->modbusMsg->setFont(font); } /// @@ -790,12 +790,10 @@ DataDisplayMode OutputWidget::dataDisplayMode() const void OutputWidget::setDataDisplayMode(DataDisplayMode mode) { _dataDisplayMode = mode; + ui->modbusMsg->setDataDisplayMode(mode); + _listModel->update(); _trafficModel->update(); - - // update traffic info - auto model = ui->logView->selectionModel(); - emit model->selectionChanged(model->selection(), QItemSelection()); } /// @@ -913,298 +911,14 @@ void OutputWidget::captureString(const QString& s) /// void OutputWidget::showTrafficInfo(const QModelIndex& index) { - ui->trafficInfo->clear(); - - if(!index.isValid()) - return; - - const auto data = _trafficModel->data(index, Qt::UserRole).value(); - const auto function = QString("%1 (%2)").arg(formatByteValue(dataDisplayMode(), data->function()), data->function()); - - ui->trafficInfo->addItem(tr("Type: %1").arg(data->isRequest() ? tr("Tx Message") : tr("Rx Message"))); - ui->trafficInfo->addItem(tr("Timestamp: %1").arg(data->timestamp().toString(Qt::ISODateWithMs))); - ui->trafficInfo->addItem(tr("Device ID: %1").arg(formatByteValue(dataDisplayMode(), data->deviceId()))); - - if(data->isException()) + if(index.isValid()) { - const auto exception = QString("%1 (%2)").arg(formatByteValue(dataDisplayMode(), data->exception()), data->exception()); - ui->trafficInfo->addItem(tr("Error Code: %1").arg(formatByteValue(dataDisplayMode(), data->function()))); - ui->trafficInfo->addItem(tr("Exception Code: %1").arg(exception)); - return; + const auto msg = _trafficModel->data(index, Qt::UserRole).value(); + ui->modbusMsg->setModbusMessage(msg); } - - ui->trafficInfo->addItem(tr("Function Code: %1").arg(function)); - - switch(data->function()) + else { - case QModbusPdu::ReadCoils: - { - if(data->isRequest()) - { - auto req = reinterpret_cast(data); - ui->trafficInfo->addItem(tr("Start Address: %1").arg(formatWordValue(dataDisplayMode(), req->startAddress()))); - ui->trafficInfo->addItem(tr("Length: %1").arg(formatWordValue(dataDisplayMode(), req->length()))); - } - else - { - auto resp = reinterpret_cast(data); - ui->trafficInfo->addItem(tr("Byte Count: %1").arg(formatByteValue(dataDisplayMode(), resp->byteCount()))); - ui->trafficInfo->addItem(tr("Coil Status: %1").arg(formatByteArray(dataDisplayMode(), resp->coilStatus()))); - } - } - break; - - case QModbusPdu::ReadDiscreteInputs: - { - if(data->isRequest()) - { - auto req = reinterpret_cast(data); - ui->trafficInfo->addItem(tr("Start Address: %1").arg(formatWordValue(dataDisplayMode(), req->startAddress()))); - ui->trafficInfo->addItem(tr("Length: %1").arg(formatWordValue(dataDisplayMode(), req->length()))); - } - else - { - auto resp = reinterpret_cast(data); - ui->trafficInfo->addItem(tr("Byte Count: %1").arg(formatByteValue(dataDisplayMode(), resp->byteCount()))); - ui->trafficInfo->addItem(tr("Input Status: %1").arg(formatByteArray(dataDisplayMode(), resp->inputStatus()))); - } - } - break; - - case QModbusPdu::ReadHoldingRegisters: - { - if(data->isRequest()) - { - auto req = reinterpret_cast(data); - ui->trafficInfo->addItem(tr("Start Address: %1").arg(formatWordValue(dataDisplayMode(), req->startAddress()))); - ui->trafficInfo->addItem(tr("Length: %1").arg(formatWordValue(dataDisplayMode(), req->length()))); - } - else - { - auto resp = reinterpret_cast(data); - ui->trafficInfo->addItem(tr("Byte Count: %1").arg(formatByteValue(dataDisplayMode(), resp->byteCount()))); - ui->trafficInfo->addItem(tr("Register Value: %1").arg(formatByteArray(dataDisplayMode(), resp->registerValue()))); - } - } - break; - - case QModbusPdu::ReadInputRegisters: - { - if(data->isRequest()) - { - auto req = reinterpret_cast(data); - ui->trafficInfo->addItem(tr("Start Address: %1").arg(formatWordValue(dataDisplayMode(), req->startAddress()))); - ui->trafficInfo->addItem(tr("Length: %1").arg(formatWordValue(dataDisplayMode(), req->length()))); - } - else - { - auto resp = reinterpret_cast(data); - ui->trafficInfo->addItem(tr("Byte Count: %1").arg(formatByteValue(dataDisplayMode(), resp->byteCount()))); - ui->trafficInfo->addItem(tr("Input Registers: %1").arg(formatByteArray(dataDisplayMode(), resp->registerValue()))); - } - } - break; - - case QModbusPdu::WriteSingleCoil: - if(data->isRequest()) - { - auto req = reinterpret_cast(data); - ui->trafficInfo->addItem(tr("Output Address: %1").arg(formatWordValue(dataDisplayMode(), req->address()))); - ui->trafficInfo->addItem(tr("Output Value: %1").arg(formatWordValue(dataDisplayMode(), req->value()))); - } - else - { - auto resp = reinterpret_cast(data); - ui->trafficInfo->addItem(tr("Output Address: %1").arg(formatWordValue(dataDisplayMode(), resp->address()))); - ui->trafficInfo->addItem(tr("Output Value: %1").arg(formatWordValue(dataDisplayMode(), resp->value()))); - } - break; - - case QModbusPdu::WriteSingleRegister: - if(data->isRequest()) - { - auto req = reinterpret_cast(data); - ui->trafficInfo->addItem(tr("Register Address: %1").arg(formatWordValue(dataDisplayMode(), req->address()))); - ui->trafficInfo->addItem(tr("Register Value: %1").arg(formatWordValue(dataDisplayMode(), req->value()))); - } - else - { - auto resp = reinterpret_cast(data); - ui->trafficInfo->addItem(tr("Register Address: %1").arg(formatWordValue(dataDisplayMode(), resp->address()))); - ui->trafficInfo->addItem(tr("Register Value: %1").arg(formatWordValue(dataDisplayMode(), resp->value()))); - } - break; - - case QModbusPdu::ReadExceptionStatus: - if(!data->isRequest()) - { - auto resp = reinterpret_cast(data); - ui->trafficInfo->addItem(tr("Output Data: %1").arg(formatByteValue(dataDisplayMode(), resp->outputData()))); - } - break; - - case QModbusPdu::Diagnostics: - if(data->isRequest()) - { - auto req = reinterpret_cast(data); - ui->trafficInfo->addItem(tr("Sub-function: %1").arg(formatWordValue(dataDisplayMode(), req->subfunc()))); - ui->trafficInfo->addItem(tr("Data: %1").arg(formatByteArray(dataDisplayMode(), req->data()))); - } - else - { - auto resp = reinterpret_cast(data); - ui->trafficInfo->addItem(tr("Sub-function: %1").arg(formatWordValue(dataDisplayMode(), resp->subfunc()))); - ui->trafficInfo->addItem(tr("Data: %1").arg(formatByteArray(dataDisplayMode(), resp->data()))); - } - break; - - case QModbusPdu::GetCommEventCounter: - if(!data->isRequest()) - { - auto resp = reinterpret_cast(data); - ui->trafficInfo->addItem(tr("Status: %1").arg(formatWordValue(dataDisplayMode(), resp->status()))); - ui->trafficInfo->addItem(tr("Event Count: %1").arg(formatWordValue(dataDisplayMode(), resp->eventCount()))); - } - break; - - case QModbusPdu::GetCommEventLog: - if(!data->isRequest()) - { - auto resp = reinterpret_cast(data); - ui->trafficInfo->addItem(tr("Byte Count: %1").arg(formatByteValue(dataDisplayMode(), resp->byteCount()))); - ui->trafficInfo->addItem(tr("Status: %1").arg(formatWordValue(dataDisplayMode(), resp->status()))); - ui->trafficInfo->addItem(tr("Event Count: %1").arg(formatWordValue(dataDisplayMode(), resp->eventCount()))); - ui->trafficInfo->addItem(tr("Message Count: %1").arg(formatWordValue(dataDisplayMode(), resp->messageCount()))); - ui->trafficInfo->addItem(tr("Events: %1").arg(formatByteArray(dataDisplayMode(), resp->events()))); - } - break; - - case QModbusPdu::WriteMultipleCoils: - if(data->isRequest()) - { - auto req = reinterpret_cast(data); - ui->trafficInfo->addItem(tr("Starting Address: %1").arg(formatWordValue(dataDisplayMode(), req->startAddress()))); - ui->trafficInfo->addItem(tr("Quantity of Outputs: %1").arg(formatWordValue(dataDisplayMode(), req->quantity()))); - ui->trafficInfo->addItem(tr("Byte Count: %1").arg(formatByteValue(dataDisplayMode(), req->byteCount()))); - ui->trafficInfo->addItem(tr("Output Value: %1").arg(formatByteArray(dataDisplayMode(), req->values()))); - } - else - { - auto resp = reinterpret_cast(data); - ui->trafficInfo->addItem(tr("Starting Address: %1").arg(formatWordValue(dataDisplayMode(), resp->startAddress()))); - ui->trafficInfo->addItem(tr("Quantity of Outputs: %1").arg(formatWordValue(dataDisplayMode(), resp->quantity()))); - } - break; - - case QModbusPdu::WriteMultipleRegisters: - if(data->isRequest()) - { - auto req = reinterpret_cast(data); - ui->trafficInfo->addItem(tr("Starting Address: %1").arg(formatWordValue(dataDisplayMode(), req->startAddress()))); - ui->trafficInfo->addItem(tr("Quantity of Registers: %1").arg(formatWordValue(dataDisplayMode(), req->quantity()))); - ui->trafficInfo->addItem(tr("Byte Count: %1").arg(formatByteValue(dataDisplayMode(), req->byteCount()))); - ui->trafficInfo->addItem(tr("Registers Value: %1").arg(formatByteArray(dataDisplayMode(), req->values()))); - } - else - { - auto resp = reinterpret_cast(data); - ui->trafficInfo->addItem(tr("Starting Address: %1").arg(formatWordValue(dataDisplayMode(), resp->startAddress()))); - ui->trafficInfo->addItem(tr("Quantity of Registers: %1").arg(formatWordValue(dataDisplayMode(), resp->quantity()))); - } - break; - - case QModbusPdu::ReportServerId: - if(!data->isRequest()) - { - auto resp = reinterpret_cast(data); - ui->trafficInfo->addItem(tr("Byte Count: %1").arg(formatByteValue(dataDisplayMode(), resp->byteCount()))); - ui->trafficInfo->addItem(tr("Data: %1").arg(formatByteArray(dataDisplayMode(), resp->data()))); - } - break; - - case QModbusPdu::ReadFileRecord: - if(data->isRequest()) - { - auto req = reinterpret_cast(data); - ui->trafficInfo->addItem(tr("Byte Count: %1").arg(formatByteValue(dataDisplayMode(), req->byteCount()))); - ui->trafficInfo->addItem(tr("Data: %1").arg(formatByteArray(dataDisplayMode(), req->data()))); - } - else - { - auto resp = reinterpret_cast(data); - ui->trafficInfo->addItem(tr("Byte Count: %1").arg(formatByteValue(dataDisplayMode(), resp->byteCount()))); - ui->trafficInfo->addItem(tr("Data: %1").arg(formatByteArray(dataDisplayMode(), resp->data()))); - } - break; - - case QModbusPdu::WriteFileRecord: - if(data->isRequest()) - { - auto req = reinterpret_cast(data); - ui->trafficInfo->addItem(tr("Request Data Length: %1").arg(formatByteValue(dataDisplayMode(), req->length()))); - ui->trafficInfo->addItem(tr("Data: %1").arg(formatByteArray(dataDisplayMode(), req->data()))); - } - else - { - auto resp = reinterpret_cast(data); - ui->trafficInfo->addItem(tr("Request Data Length: %1").arg(formatByteValue(dataDisplayMode(), resp->length()))); - ui->trafficInfo->addItem(tr("Data: %1").arg(formatByteArray(dataDisplayMode(), resp->data()))); - } - break; - - case QModbusPdu::MaskWriteRegister: - if(data->isRequest()) - { - auto req = reinterpret_cast(data); - ui->trafficInfo->addItem(tr("Address: %1").arg(formatWordValue(dataDisplayMode(), req->address()))); - ui->trafficInfo->addItem(tr("And Mask: %1").arg(formatWordValue(dataDisplayMode(), req->andMask()))); - ui->trafficInfo->addItem(tr("Or Mask: %1").arg(formatWordValue(dataDisplayMode(), req->orMask()))); - } - else - { - auto resp = reinterpret_cast(data); - ui->trafficInfo->addItem(tr("Address: %1").arg(formatWordValue(dataDisplayMode(), resp->address()))); - ui->trafficInfo->addItem(tr("And Mask: %1").arg(formatWordValue(dataDisplayMode(), resp->andMask()))); - ui->trafficInfo->addItem(tr("Or Mask: %1").arg(formatWordValue(dataDisplayMode(), resp->orMask()))); - } - break; - - case QModbusPdu::ReadWriteMultipleRegisters: - if(data->isRequest()) - { - auto req = reinterpret_cast(data); - ui->trafficInfo->addItem(tr("Read Starting Address: %1").arg(formatWordValue(dataDisplayMode(), req->readStartAddress()))); - ui->trafficInfo->addItem(tr("Quantity to Read: %1").arg(formatWordValue(dataDisplayMode(), req->readLength()))); - ui->trafficInfo->addItem(tr("Write Starting Address: %1").arg(formatWordValue(dataDisplayMode(), req->writeStartAddress()))); - ui->trafficInfo->addItem(tr("Quantity to Write: %1").arg(formatWordValue(dataDisplayMode(), req->writeLength()))); - ui->trafficInfo->addItem(tr("Write Byte Count: %1").arg(formatByteValue(dataDisplayMode(), req->writeByteCount()))); - ui->trafficInfo->addItem(tr("Write Registers Value: %1").arg(formatByteArray(dataDisplayMode(), req->writeValues()))); - } - else - { - auto resp = reinterpret_cast(data); - ui->trafficInfo->addItem(tr("Byte Count: %1").arg(formatByteValue(dataDisplayMode(), resp->byteCount()))); - ui->trafficInfo->addItem(tr("Registers Value: %1").arg(formatByteArray(dataDisplayMode(), resp->values()))); - } - break; - - case QModbusPdu::ReadFifoQueue: - if(data->isRequest()) - { - auto req = reinterpret_cast(data); - ui->trafficInfo->addItem(tr("FIFO Point Address: %1").arg(formatWordValue(dataDisplayMode(), req->fifoAddress()))); - } - else - { - auto resp = reinterpret_cast(data); - ui->trafficInfo->addItem(tr("Byte Count: %1").arg(formatByteValue(dataDisplayMode(), resp->byteCount()))); - ui->trafficInfo->addItem(tr("FIFO Count: %1").arg(formatByteValue(dataDisplayMode(), resp->fifoCount()))); - ui->trafficInfo->addItem(tr("FIFO Value Register: %1").arg(formatByteArray(dataDisplayMode(), resp->fifoValue()))); - } - break; - - default: - break; + ui->modbusMsg->clear(); } } diff --git a/omodscan/controls/outputwidget.ui b/omodscan/controls/outputwidget.ui index a8ea2a1..8b8afcf 100644 --- a/omodscan/controls/outputwidget.ui +++ b/omodscan/controls/outputwidget.ui @@ -163,7 +163,7 @@ true - + 0 @@ -188,6 +188,13 @@ + + + ModbusMessageWidget + QListWidget +
modbusmessagewidget.h
+
+
diff --git a/omodscan/formatutils.h b/omodscan/formatutils.h index 2b09842..ffcd699 100644 --- a/omodscan/formatutils.h +++ b/omodscan/formatutils.h @@ -36,8 +36,8 @@ inline QString formatByteValue(DataDisplayMode mode, uchar c) inline QString formatByteArray(DataDisplayMode mode, const QByteArray& ar) { QStringList values; - for(auto i = 0; i < ar.size(); i++) - values += formatByteValue(mode, ar[i]); + for(auto&& i : ar) + values += formatByteValue(mode, i); return values.join(" "); } diff --git a/omodscan/modbusmessages/modbusmessage.h b/omodscan/modbusmessages/modbusmessage.h index eb0c330..fceacb5 100644 --- a/omodscan/modbusmessages/modbusmessage.h +++ b/omodscan/modbusmessages/modbusmessage.h @@ -95,11 +95,17 @@ class ModbusMessage rawData.push_back(_funcCode); rawData.push_back(_data); - QStringList data; - for(auto&& c : rawData) - data += formatByteValue(mode, c); + return formatByteArray(mode, rawData); + } - return data.join(" "); + /// + /// \brief data + /// \param mode + /// \return + /// + QString data(DataDisplayMode mode) const + { + return formatByteArray(mode, _data); } protected: diff --git a/omodscan/omodscan.pro b/omodscan/omodscan.pro index 17e9222..058eba0 100644 --- a/omodscan/omodscan.pro +++ b/omodscan/omodscan.pro @@ -36,6 +36,7 @@ SOURCES += \ controls/functioncodecombobox.cpp \ controls/ipaddresslineedit.cpp \ controls/mainstatusbar.cpp \ + controls/modbusmessagewidget.cpp \ controls/numericlineedit.cpp \ controls/paritytypecombobox.cpp \ controls/simulationmodecombobox.cpp \ @@ -94,6 +95,7 @@ HEADERS += \ controls/functioncodecombobox.h \ controls/ipaddresslineedit.h \ controls/mainstatusbar.h \ + controls/modbusmessagewidget.h \ controls/numericlineedit.h \ controls/paritytypecombobox.h \ controls/simulationmodecombobox.h \ From ac5b4a61d8a948a879aebf2f8b841f5ee996a1eb Mon Sep 17 00:00:00 2001 From: sanny32 Date: Thu, 28 Sep 2023 09:37:11 +0300 Subject: [PATCH 10/90] Developing new log view --- omodscan/controls/modbuslogwidget.cpp | 196 ++++++++++++++++++++++ omodscan/controls/modbuslogwidget.h | 65 +++++++ omodscan/controls/modbusmessagewidget.cpp | 2 + omodscan/controls/outputwidget.cpp | 137 ++------------- omodscan/controls/outputwidget.h | 31 +--- omodscan/controls/outputwidget.ui | 7 +- omodscan/omodscan.pro | 2 + 7 files changed, 284 insertions(+), 156 deletions(-) create mode 100644 omodscan/controls/modbuslogwidget.cpp create mode 100644 omodscan/controls/modbuslogwidget.h diff --git a/omodscan/controls/modbuslogwidget.cpp b/omodscan/controls/modbuslogwidget.cpp new file mode 100644 index 0000000..e6ee976 --- /dev/null +++ b/omodscan/controls/modbuslogwidget.cpp @@ -0,0 +1,196 @@ +#include "htmldelegate.h" +#include "modbuslogwidget.h" + +/// +/// \brief ModbusLogModel::ModbusLogModel +/// \param parent +/// +ModbusLogModel::ModbusLogModel(ModbusLogWidget* parent) + : QAbstractListModel(parent) + ,_parentWidget(parent) +{ +} + +/// +/// \brief ModbusLogModel::~ModbusLogModel +/// +ModbusLogModel::~ModbusLogModel() +{ + deleteItems(); +} + +/// +/// \brief ModbusLogModel::rowCount +/// \param parent +/// \return +/// +int ModbusLogModel::rowCount(const QModelIndex&) const +{ + return _items.size(); +} + +/// +/// \brief ModbusLogModel::data +/// \param index +/// \param role +/// \return +/// +QVariant ModbusLogModel::data(const QModelIndex& index, int role) const +{ + if(!index.isValid() || index.row() >= rowCount()) + return QVariant(); + + const auto& item = _items.at(index.row()); + switch(role) + { + case Qt::DisplayRole: + return QString("%1 %2 %3").arg(item->timestamp().toString(Qt::ISODateWithMs), + (item->isRequest()? "→" : "←"), + item->toString(_parentWidget->dataDisplayMode())); + + + case Qt::UserRole: + return QVariant::fromValue(item); + } + + return QVariant(); +} + +/// +/// \brief ModbusLogModel::clear +/// +void ModbusLogModel::clear() +{ + beginResetModel(); + deleteItems(); + endResetModel(); +} + +/// +/// \brief ModbusLogModel::append +/// \param data +/// +void ModbusLogModel::append(const ModbusMessage* data) +{ + if(data == nullptr) return; + + if(rowCount() >= _rowLimit) + _items.removeFirst(); + + beginInsertRows(QModelIndex(), rowCount(), rowCount()); + _items.push_back(data); + endInsertRows(); +} + +/// +/// \brief ModbusLogModel::rowLimit +/// \return +/// +int ModbusLogModel::rowLimit() const +{ + return _rowLimit; +} + +/// +/// \brief ModbusLogModel::setRowLimit +/// \param val +/// +void ModbusLogModel::setRowLimit(int val) +{ + _rowLimit = qMax(1, val); +} + +/// +/// \brief ModbusLogModel::deleteItems +/// +void ModbusLogModel::deleteItems() +{ + for(auto&& i : _items) + delete i; + + _items.clear(); +} + +/// +/// \brief ModbusLogWidget::ModbusLogWidget +/// \param parent +/// +ModbusLogWidget::ModbusLogWidget(QWidget* parent) + : QListView(parent) +{ + setItemDelegate(new HtmlDelegate(this)); + setModel(new ModbusLogModel(this)); + + connect(model(), &ModbusLogModel::rowsInserted, + this, &ModbusLogWidget::scrollToBottom); +} + +/// +/// \brief ModbusLogWidget::clear +/// +void ModbusLogWidget::clear() +{ + ((ModbusLogModel*)model())->clear(); +} + +/// +/// \brief ModbusLogWidget::addItem +/// \param pdu +/// \param timestamp +/// \param deviceId +/// \param request +/// +void ModbusLogWidget::addItem(const QModbusPdu& pdu, const QDateTime& timestamp, int deviceId, bool request) +{ + ((ModbusLogModel*)model())->append(ModbusMessage::create(pdu, timestamp, deviceId, request)); +} + +/// +/// \brief ModbusLogWidget::itemAt +/// \param index +/// \return +/// +const ModbusMessage* ModbusLogWidget::itemAt(const QModelIndex& index) +{ + if(!index.isValid()) + return nullptr; + + return model()->data(index, Qt::UserRole).value(); +} + +/// +/// \brief ModbusLogWidget::dataDisplayMode +/// \return +/// +DataDisplayMode ModbusLogWidget::dataDisplayMode() const +{ + return _dataDisplayMode; +} + +/// +/// \brief ModbusLogWidget::setDataDisplayMode +/// \param mode +/// +void ModbusLogWidget::setDataDisplayMode(DataDisplayMode mode) +{ + _dataDisplayMode = mode; + ((ModbusLogModel*)model())->update(); +} + +/// +/// \brief ModbusLogWidget::rowLimit +/// \return +/// +int ModbusLogWidget::rowLimit() const +{ + return ((ModbusLogModel*)model())->rowLimit(); +} + +/// +/// \brief ModbusLogWidget::setRowLimit +/// \param val +/// +void ModbusLogWidget::setRowLimit(int val) +{ + ((ModbusLogModel*)model())->setRowLimit(val); +} diff --git a/omodscan/controls/modbuslogwidget.h b/omodscan/controls/modbuslogwidget.h new file mode 100644 index 0000000..626748d --- /dev/null +++ b/omodscan/controls/modbuslogwidget.h @@ -0,0 +1,65 @@ +#ifndef MODBUSLOGWIDGET_H +#define MODBUSLOGWIDGET_H + +#include +#include +#include "modbusmessage.h" + +class ModbusLogWidget; + +/// +/// \brief The ModbusLogModel class +/// +class ModbusLogModel : public QAbstractListModel +{ + Q_OBJECT + +public: + explicit ModbusLogModel(ModbusLogWidget* parent); + ~ModbusLogModel(); + + int rowCount(const QModelIndex& parent = QModelIndex()) const override; + QVariant data(const QModelIndex& index, int role) const override; + + void clear(); + void append(const ModbusMessage* data); + void update(){ + emit dataChanged(index(0), index(_items.size() - 1)); + } + + int rowLimit() const; + void setRowLimit(int val); + +private: + void deleteItems(); + +private: + int _rowLimit = 3600; + ModbusLogWidget* _parentWidget; + QQueue _items; +}; + +/// +/// \brief The ModbusLogWidget class +/// +class ModbusLogWidget : public QListView +{ + Q_OBJECT +public: + explicit ModbusLogWidget(QWidget* parent = nullptr); + + void clear(); + void addItem(const QModbusPdu& pdu, const QDateTime& timestamp, int deviceId, bool request); + const ModbusMessage* itemAt(const QModelIndex& index); + + DataDisplayMode dataDisplayMode() const; + void setDataDisplayMode(DataDisplayMode mode); + + int rowLimit() const; + void setRowLimit(int val); + +private: + DataDisplayMode _dataDisplayMode; +}; + +#endif // MODBUSLOGWIDGET_H diff --git a/omodscan/controls/modbusmessagewidget.cpp b/omodscan/controls/modbusmessagewidget.cpp index c4f7b2f..9e01173 100644 --- a/omodscan/controls/modbusmessagewidget.cpp +++ b/omodscan/controls/modbusmessagewidget.cpp @@ -1,4 +1,5 @@ #include "formatutils.h" +#include "htmldelegate.h" #include "modbusmessagewidget.h" #include "modbusmessages.h" @@ -10,6 +11,7 @@ ModbusMessageWidget::ModbusMessageWidget(QWidget *parent) : QListWidget(parent) ,_msg(nullptr) { + setItemDelegate(new HtmlDelegate(this)); } /// diff --git a/omodscan/controls/outputwidget.cpp b/omodscan/controls/outputwidget.cpp index 70882f9..fbfbf1c 100644 --- a/omodscan/controls/outputwidget.cpp +++ b/omodscan/controls/outputwidget.cpp @@ -284,103 +284,6 @@ QModelIndex OutputListModel::find(QModbusDataUnit::RegisterType type, quint16 ad return QModelIndex(); } -/// -/// \brief TrafficModel::TrafficModel -/// \param parent -/// -TrafficModel::TrafficModel(OutputWidget* parent) - : QAbstractListModel(parent) - ,_parentWidget(parent) -{ -} - -/// -/// \brief TrafficModel::~TrafficModel -/// -TrafficModel::~TrafficModel() -{ - for(auto&& i : _items) - { - delete i; - } -} - -/// -/// \brief TrafficModel::columnCount -/// \param parent -/// \return -/// -int TrafficModel::columnCount(const QModelIndex&) const -{ - return 3; -} - -/// -/// \brief TrafficModel::rowCount -/// \param parent -/// \return -/// -int TrafficModel::rowCount(const QModelIndex&) const -{ - return _items.size(); -} - -/// -/// \brief TrafficModel::data -/// \param index -/// \param role -/// \return -/// -QVariant TrafficModel::data(const QModelIndex& index, int role) const -{ - if(!index.isValid() || index.row() >= rowCount()) - return QVariant(); - - const auto& item = _items.at(index.row()); - switch(role) - { - case Qt::DisplayRole: - return QString("%1 %2 %3").arg(item->timestamp().toString(Qt::ISODateWithMs), - (item->isRequest()? "→" : "←"), - item->toString(_parentWidget->dataDisplayMode())); - - - case Qt::UserRole: - return QVariant::fromValue(item); - } - - return QVariant(); -} - -/// -/// \brief TrafficModel::clear -/// -void TrafficModel::clear() -{ - beginResetModel(); - - for(auto&& i : _items) - { - delete i; - } - _items.clear(); - - endResetModel(); -} - -/// -/// \brief TrafficModel::append -/// \param data -/// -void TrafficModel::append(const ModbusMessage* data) -{ - if(data == nullptr) return; - - beginInsertRows(QModelIndex(), rowCount(), rowCount()); - _items.push_back(data); - endInsertRows(); -} - /// /// \brief OutputWidget::OutputWidget /// \param parent @@ -393,12 +296,10 @@ OutputWidget::OutputWidget(QWidget *parent) : ,_dataDisplayMode(DataDisplayMode::Binary) ,_byteOrder(ByteOrder::LittleEndian) ,_listModel(new OutputListModel(this)) - ,_trafficModel(new TrafficModel(this)) { ui->setupUi(this); ui->stackedWidget->setCurrentIndex(0); ui->listView->setModel(_listModel.get()); - ui->logView->setModel(_trafficModel.get()); ui->labelStatus->setAutoFillBackground(true); setAutoFillBackground(true); @@ -408,23 +309,14 @@ OutputWidget::OutputWidget(QWidget *parent) : setStatusColor(Qt::red); setUninitializedStatus(); - ui->logView->setItemDelegate(new HtmlDelegate(this)); - ui->modbusMsg->setItemDelegate(new HtmlDelegate(this)); - connect(ui->logView->selectionModel(), &QItemSelectionModel::selectionChanged, this, [&](const QItemSelection& sel) { if(sel.indexes().isEmpty()) ui->modbusMsg->clear(); else - showTrafficInfo(sel.indexes().first()); + showModbusMessage(sel.indexes().first()); }); - - connect(_trafficModel.get(), &TrafficModel::rowsInserted, - this, [&](const QModelIndex&, int first, int last) { - const auto index = _trafficModel->index(first); - ui->logView->scrollTo(index); - }); } /// @@ -679,7 +571,7 @@ void OutputWidget::paint(const QRect& rc, QPainter& painter) /// void OutputWidget::updateTraffic(const QModbusRequest& request, int server) { - updateTrafficWidget(true, server, request); + updateLogView(true, server, request); } /// @@ -689,7 +581,7 @@ void OutputWidget::updateTraffic(const QModbusRequest& request, int server) /// void OutputWidget::updateTraffic(const QModbusResponse& response, int server) { - updateTrafficWidget(false, server, response); + updateLogView(false, server, response); } /// @@ -790,10 +682,10 @@ DataDisplayMode OutputWidget::dataDisplayMode() const void OutputWidget::setDataDisplayMode(DataDisplayMode mode) { _dataDisplayMode = mode; + ui->logView->setDataDisplayMode(mode); ui->modbusMsg->setDataDisplayMode(mode); _listModel->update(); - _trafficModel->update(); } /// @@ -906,28 +798,21 @@ void OutputWidget::captureString(const QString& s) } /// -/// \brief OutputWidget::showTrafficInfo +/// \brief OutputWidget::showModbusMessage /// \param index /// -void OutputWidget::showTrafficInfo(const QModelIndex& index) +void OutputWidget::showModbusMessage(const QModelIndex& index) { - if(index.isValid()) - { - const auto msg = _trafficModel->data(index, Qt::UserRole).value(); - ui->modbusMsg->setModbusMessage(msg); - } - else - { - ui->modbusMsg->clear(); - } + const auto msg = ui->logView->itemAt(index); + ui->modbusMsg->setModbusMessage(msg); } /// -/// \brief OutputWidget::updateTrafficWidget +/// \brief OutputWidget::updateLogView /// \param request /// \param pdu /// -void OutputWidget::updateTrafficWidget(bool request, int server, const QModbusPdu& pdu) +void OutputWidget::updateLogView(bool request, int server, const QModbusPdu& pdu) { - _trafficModel->append(ModbusMessage::create(pdu, QDateTime::currentDateTime(), server, request)); + ui->logView->addItem(pdu, QDateTime::currentDateTime(), server, request); } diff --git a/omodscan/controls/outputwidget.h b/omodscan/controls/outputwidget.h index 3bef5d2..610e3e3 100644 --- a/omodscan/controls/outputwidget.h +++ b/omodscan/controls/outputwidget.h @@ -60,32 +60,6 @@ class OutputListModel : public QAbstractListModel QMap _mapItems; }; -/// -/// \brief The TrafficModel class -/// -class TrafficModel : public QAbstractListModel -{ - Q_OBJECT - -public: - explicit TrafficModel(OutputWidget* parent); - ~TrafficModel(); - - int columnCount(const QModelIndex &parent = QModelIndex()) const override; - int rowCount(const QModelIndex& parent = QModelIndex()) const override; - QVariant data(const QModelIndex& index, int role) const override; - - void clear(); - void append(const ModbusMessage* data); - void update(){ - emit dataChanged(index(0), index(_items.size() - 1)); - } - -private: - OutputWidget* _parentWidget; - QVector _items; -}; - /// /// \brief The OutputWidget class /// @@ -157,8 +131,8 @@ private slots: private: void setUninitializedStatus(); void captureString(const QString& s); - void showTrafficInfo(const QModelIndex& index); - void updateTrafficWidget(bool request, int server, const QModbusPdu& pdu); + void showModbusMessage(const QModelIndex& index); + void updateLogView(bool request, int server, const QModbusPdu& pdu); private: Ui::OutputWidget *ui; @@ -172,7 +146,6 @@ private slots: QFile _fileCapture; AddressDescriptionMap _descriptionMap; QSharedPointer _listModel; - QSharedPointer _trafficModel; }; #endif // OUTPUTWIDGET_H diff --git a/omodscan/controls/outputwidget.ui b/omodscan/controls/outputwidget.ui index 8b8afcf..a003891 100644 --- a/omodscan/controls/outputwidget.ui +++ b/omodscan/controls/outputwidget.ui @@ -128,7 +128,7 @@ Qt::Vertical - + 0 @@ -194,6 +194,11 @@ QListWidget
modbusmessagewidget.h
+ + ModbusLogWidget + QListView +
modbuslogwidget.h
+
diff --git a/omodscan/omodscan.pro b/omodscan/omodscan.pro index 058eba0..deaa8b6 100644 --- a/omodscan/omodscan.pro +++ b/omodscan/omodscan.pro @@ -36,6 +36,7 @@ SOURCES += \ controls/functioncodecombobox.cpp \ controls/ipaddresslineedit.cpp \ controls/mainstatusbar.cpp \ + controls/modbuslogwidget.cpp \ controls/modbusmessagewidget.cpp \ controls/numericlineedit.cpp \ controls/paritytypecombobox.cpp \ @@ -95,6 +96,7 @@ HEADERS += \ controls/functioncodecombobox.h \ controls/ipaddresslineedit.h \ controls/mainstatusbar.h \ + controls/modbuslogwidget.h \ controls/modbusmessagewidget.h \ controls/numericlineedit.h \ controls/paritytypecombobox.h \ From e838570f176594f893c4b912ebf02826d395032e Mon Sep 17 00:00:00 2001 From: sanny32 Date: Thu, 28 Sep 2023 16:34:18 +0300 Subject: [PATCH 11/90] Developing new log view --- omodscan/controls/modbuslogwidget.cpp | 11 ++++++++++- omodscan/controls/modbuslogwidget.h | 2 +- omodscan/controls/outputwidget.cpp | 4 +--- omodscan/htmldelegate.cpp | 2 ++ omodscan/modbusmessages/modbusmessage.h | 2 +- 5 files changed, 15 insertions(+), 6 deletions(-) diff --git a/omodscan/controls/modbuslogwidget.cpp b/omodscan/controls/modbuslogwidget.cpp index e6ee976..0064e33 100644 --- a/omodscan/controls/modbuslogwidget.cpp +++ b/omodscan/controls/modbuslogwidget.cpp @@ -47,6 +47,9 @@ QVariant ModbusLogModel::data(const QModelIndex& index, int role) const return QString("%1 %2 %3").arg(item->timestamp().toString(Qt::ISODateWithMs), (item->isRequest()? "→" : "←"), item->toString(_parentWidget->dataDisplayMode())); + /*return QString("%1 %2 %3").arg(item->timestamp().toString(Qt::ISODateWithMs), + (item->isRequest()? ">>" : "<<"), + item->toString(_parentWidget->dataDisplayMode()));*/ case Qt::UserRole: @@ -75,7 +78,10 @@ void ModbusLogModel::append(const ModbusMessage* data) if(data == nullptr) return; if(rowCount() >= _rowLimit) + { + delete _items.first(); _items.removeFirst(); + } beginInsertRows(QModelIndex(), rowCount(), rowCount()); _items.push_back(data); @@ -122,7 +128,10 @@ ModbusLogWidget::ModbusLogWidget(QWidget* parent) setModel(new ModbusLogModel(this)); connect(model(), &ModbusLogModel::rowsInserted, - this, &ModbusLogWidget::scrollToBottom); + this, [&]{ + scrollToBottom(); + setCurrentIndex(QModelIndex()); + }); } /// diff --git a/omodscan/controls/modbuslogwidget.h b/omodscan/controls/modbuslogwidget.h index 626748d..616d6a7 100644 --- a/omodscan/controls/modbuslogwidget.h +++ b/omodscan/controls/modbuslogwidget.h @@ -34,7 +34,7 @@ class ModbusLogModel : public QAbstractListModel void deleteItems(); private: - int _rowLimit = 3600; + int _rowLimit = 60; ModbusLogWidget* _parentWidget; QQueue _items; }; diff --git a/omodscan/controls/outputwidget.cpp b/omodscan/controls/outputwidget.cpp index fbfbf1c..b1a1a15 100644 --- a/omodscan/controls/outputwidget.cpp +++ b/omodscan/controls/outputwidget.cpp @@ -312,9 +312,7 @@ OutputWidget::OutputWidget(QWidget *parent) : connect(ui->logView->selectionModel(), &QItemSelectionModel::selectionChanged, this, [&](const QItemSelection& sel) { - if(sel.indexes().isEmpty()) - ui->modbusMsg->clear(); - else + if(!sel.indexes().isEmpty()) showModbusMessage(sel.indexes().first()); }); } diff --git a/omodscan/htmldelegate.cpp b/omodscan/htmldelegate.cpp index f0a9f92..4fd7204 100644 --- a/omodscan/htmldelegate.cpp +++ b/omodscan/htmldelegate.cpp @@ -41,6 +41,7 @@ void HtmlDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, QTextDocument doc; doc.setHtml(opt.text); + doc.setDocumentMargin(0); doc.setDefaultFont(opt.font); doc.setDefaultTextOption(textOption); doc.setTextWidth(opt.rect.width()); @@ -81,6 +82,7 @@ QSize HtmlDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelInd QTextDocument doc; doc.setHtml(opt.text); + doc.setDocumentMargin(0); doc.setDefaultFont(opt.font); doc.setTextWidth(opt.rect.width()); diff --git a/omodscan/modbusmessages/modbusmessage.h b/omodscan/modbusmessages/modbusmessage.h index fceacb5..c0487cd 100644 --- a/omodscan/modbusmessages/modbusmessage.h +++ b/omodscan/modbusmessages/modbusmessage.h @@ -94,7 +94,6 @@ class ModbusMessage rawData.push_back(_deviceId); rawData.push_back(_funcCode); rawData.push_back(_data); - return formatByteArray(mode, rawData); } @@ -136,5 +135,6 @@ class ModbusMessage const int _deviceId; const bool _request; }; +Q_DECLARE_METATYPE(const ModbusMessage*) #endif // MODBUSMESSAGE_H From 91cce3e8f69d7dd74bf33be8bdaddce37a811a9f Mon Sep 17 00:00:00 2001 From: sanny32 Date: Fri, 29 Sep 2023 11:30:17 +0300 Subject: [PATCH 12/90] Developing new log view --- omodscan/controls/modbuslogwidget.cpp | 8 +- omodscan/controls/modbuslogwidget.h | 2 +- omodscan/controls/outputwidget.cpp | 20 +++ omodscan/controls/outputwidget.h | 3 + omodscan/dialogs/dialogdisplaydefinition.cpp | 5 +- omodscan/dialogs/dialogdisplaydefinition.ui | 140 ++++++++++++------- omodscan/displaydefinition.h | 4 + omodscan/formmodsca.cpp | 98 +++++++++---- omodscan/formmodsca.h | 11 +- omodscan/htmldelegate.cpp | 4 +- omodscan/modbusexception.h | 4 +- omodscan/modbusfunction.h | 4 +- 12 files changed, 205 insertions(+), 98 deletions(-) diff --git a/omodscan/controls/modbuslogwidget.cpp b/omodscan/controls/modbuslogwidget.cpp index 0064e33..4ba2162 100644 --- a/omodscan/controls/modbuslogwidget.cpp +++ b/omodscan/controls/modbuslogwidget.cpp @@ -47,10 +47,6 @@ QVariant ModbusLogModel::data(const QModelIndex& index, int role) const return QString("%1 %2 %3").arg(item->timestamp().toString(Qt::ISODateWithMs), (item->isRequest()? "→" : "←"), item->toString(_parentWidget->dataDisplayMode())); - /*return QString("%1 %2 %3").arg(item->timestamp().toString(Qt::ISODateWithMs), - (item->isRequest()? ">>" : "<<"), - item->toString(_parentWidget->dataDisplayMode()));*/ - case Qt::UserRole: return QVariant::fromValue(item); @@ -77,7 +73,7 @@ void ModbusLogModel::append(const ModbusMessage* data) { if(data == nullptr) return; - if(rowCount() >= _rowLimit) + while(rowCount() >= _rowLimit) { delete _items.first(); _items.removeFirst(); @@ -129,7 +125,7 @@ ModbusLogWidget::ModbusLogWidget(QWidget* parent) connect(model(), &ModbusLogModel::rowsInserted, this, [&]{ - scrollToBottom(); + //scrollToBottom(); setCurrentIndex(QModelIndex()); }); } diff --git a/omodscan/controls/modbuslogwidget.h b/omodscan/controls/modbuslogwidget.h index 616d6a7..637591a 100644 --- a/omodscan/controls/modbuslogwidget.h +++ b/omodscan/controls/modbuslogwidget.h @@ -34,7 +34,7 @@ class ModbusLogModel : public QAbstractListModel void deleteItems(); private: - int _rowLimit = 60; + int _rowLimit = 30; ModbusLogWidget* _parentWidget; QQueue _items; }; diff --git a/omodscan/controls/outputwidget.cpp b/omodscan/controls/outputwidget.cpp index b1a1a15..f8428f6 100644 --- a/omodscan/controls/outputwidget.cpp +++ b/omodscan/controls/outputwidget.cpp @@ -359,6 +359,8 @@ void OutputWidget::setup(const DisplayDefinition& dd, const ModbusSimulationMap& _descriptionMap.insert(descriptionMap()); _displayDefinition = dd; + setLogViewLimit(dd.LogViewLimit); + _listModel->clear(); for(auto&& key : simulations.keys()) @@ -499,6 +501,24 @@ void OutputWidget::setFont(const QFont& font) ui->modbusMsg->setFont(font); } +/// +/// \brief OutputWidget::logViewLimit +/// \return +/// +int OutputWidget::logViewLimit() const +{ + return ui->logView->rowLimit(); +} + +/// +/// \brief OutputWidget::setLogViewLimit +/// \param l +/// +void OutputWidget::setLogViewLimit(int l) +{ + ui->logView->setRowLimit(l); +} + /// /// \brief OutputWidget::setStatus /// \param status diff --git a/omodscan/controls/outputwidget.h b/omodscan/controls/outputwidget.h index 610e3e3..51a9998 100644 --- a/omodscan/controls/outputwidget.h +++ b/omodscan/controls/outputwidget.h @@ -105,6 +105,9 @@ class OutputWidget : public QWidget QFont font() const; void setFont(const QFont& font); + int logViewLimit() const; + void setLogViewLimit(int l); + void setStatus(const QString& status); void paint(const QRect& rc, QPainter& painter); diff --git a/omodscan/dialogs/dialogdisplaydefinition.cpp b/omodscan/dialogs/dialogdisplaydefinition.cpp index a4c5988..9febb67 100644 --- a/omodscan/dialogs/dialogdisplaydefinition.cpp +++ b/omodscan/dialogs/dialogdisplaydefinition.cpp @@ -12,16 +12,18 @@ DialogDisplayDefinition::DialogDisplayDefinition(FormModSca* parent) : ui(new Ui::DialogDisplayDefinition) { ui->setupUi(this); - ui->lineEditScanRate->setInputRange(20, 10000); + ui->lineEditScanRate->setInputRange(20, 36000000); ui->lineEditPointAddress->setInputRange(ModbusLimits::addressRange()); ui->lineEditLength->setInputRange(ModbusLimits::lengthRange()); ui->lineEditSlaveAddress->setInputRange(ModbusLimits::slaveRange()); + ui->lineEditLogLimit->setInputRange(4, 1000); const auto dd = parent->displayDefinition(); ui->lineEditScanRate->setValue(dd.ScanRate); ui->lineEditPointAddress->setValue(dd.PointAddress); ui->lineEditSlaveAddress->setValue(dd.DeviceId); ui->lineEditLength->setValue(dd.Length); + ui->lineEditLogLimit->setValue(dd.LogViewLimit); ui->comboBoxPointType->setCurrentPointType(dd.PointType); ui->buttonBox->setFocus(); @@ -46,6 +48,7 @@ void DialogDisplayDefinition::accept() dd.PointType = ui->comboBoxPointType->currentPointType(); dd.Length = ui->lineEditLength->value(); dd.ScanRate = ui->lineEditScanRate->value(); + dd.LogViewLimit = ui->lineEditLogLimit->value(); ((FormModSca*)parentWidget())->setDisplayDefinition(dd); QFixedSizeDialog::accept(); diff --git a/omodscan/dialogs/dialogdisplaydefinition.ui b/omodscan/dialogs/dialogdisplaydefinition.ui index 4fbf4f0..bde2209 100644 --- a/omodscan/dialogs/dialogdisplaydefinition.ui +++ b/omodscan/dialogs/dialogdisplaydefinition.ui @@ -7,7 +7,7 @@ 0 0 350 - 262 + 277
@@ -15,68 +15,104 @@ - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + Qt::AlignHCenter|Qt::AlignTop + + + 40 + + + 9 + + + 9 + + + 9 + + Scan Rate: - - - - - 0 - 0 - - - - - 0 - 25 - - - - - 60 - 16777215 - - - + + + + + + + 0 + 0 + + + + + 0 + 25 + + + + + 60 + 16777215 + + + + + + + + (msecs) + + + + - - + + - (msecs) + Log View Limit: - - - - Qt::Horizontal - - - - 40 - 20 - - - + + + + + + + 0 + 0 + + + + + 0 + 25 + + + + + 60 + 16777215 + + + + + + + + (rows) + + + + diff --git a/omodscan/displaydefinition.h b/omodscan/displaydefinition.h index c7a01c2..f3798db 100644 --- a/omodscan/displaydefinition.h +++ b/omodscan/displaydefinition.h @@ -15,6 +15,7 @@ struct DisplayDefinition quint16 PointAddress = 1; QModbusDataUnit::RegisterType PointType = QModbusDataUnit::Coils; quint16 Length = 50; + quint16 LogViewLimit = 30; void normalize() { @@ -23,6 +24,7 @@ struct DisplayDefinition PointAddress = qMax(ModbusLimits::addressRange().from(), PointAddress); PointType = qBound(QModbusDataUnit::DiscreteInputs, PointType, QModbusDataUnit::HoldingRegisters); Length = qBound(ModbusLimits::lengthRange().from(), Length, ModbusLimits::lengthRange().to()); + LogViewLimit = qBound(4, LogViewLimit, 1000); } }; Q_DECLARE_METATYPE(DisplayDefinition) @@ -34,6 +36,7 @@ inline QSettings& operator <<(QSettings& out, const DisplayDefinition& dd) out.setValue("DisplayDefinition/PointAddress", dd.PointAddress); out.setValue("DisplayDefinition/PointType", dd.PointType); out.setValue("DisplayDefinition/Length", dd.Length); + out.setValue("DisplayDefinition/LogViewLimit", dd.LogViewLimit); return out; } @@ -51,6 +54,7 @@ inline QSettings& operator >>(QSettings& in, DisplayDefinition& dd) dd.PointAddress = in.value("DisplayDefinition/PointAddress", 1).toUInt(); dd.PointType = (QModbusDataUnit::RegisterType)in.value("DisplayDefinition/PointType", 1).toUInt(); dd.Length = in.value("DisplayDefinition/Length", 50).toUInt(); + dd.LogViewLimit = in.value("DisplayDefinition/LogViewLimit", 30).toUInt(); dd.normalize(); return in; diff --git a/omodscan/formmodsca.cpp b/omodscan/formmodsca.cpp index f4db92a..4aa55b2 100644 --- a/omodscan/formmodsca.cpp +++ b/omodscan/formmodsca.cpp @@ -10,7 +10,7 @@ #include "formmodsca.h" #include "ui_formmodsca.h" -QVersionNumber FormModSca::VERSION = QVersionNumber(1, 3); +QVersionNumber FormModSca::VERSION = QVersionNumber(1, 4); /// /// \brief FormModSca::FormModSca @@ -52,13 +52,13 @@ FormModSca::FormModSca(int id, ModbusClient& client, QSharedPointerlineEditAddress->value(); dd.PointType = ui->comboBoxModbusPointType->currentPointType(); dd.Length = ui->lineEditLength->value(); + dd.LogViewLimit = ui->outputWidget->logViewLimit(); return dd; } @@ -132,7 +133,7 @@ DisplayDefinition FormModSca::displayDefinition() const /// void FormModSca::setDisplayDefinition(const DisplayDefinition& dd) { - _timer.setInterval(qBound(20U, dd.ScanRate, 10000U)); + _timer.setInterval(dd.ScanRate); ui->lineEditDeviceId->setValue(dd.DeviceId); ui->lineEditAddress->setValue(dd.PointAddress); ui->lineEditLength->setValue(dd.Length); @@ -140,6 +141,7 @@ void FormModSca::setDisplayDefinition(const DisplayDefinition& dd) ui->outputWidget->setStatus(tr("Data Uninitialized")); ui->outputWidget->setup(dd, _dataSimulator->simulationMap(dd.DeviceId)); + beginUpdate(); } /// @@ -470,30 +472,40 @@ void FormModSca::show() /// void FormModSca::on_timeout() { - if(!_modbusClient.isValid()) return; if(_modbusClient.state() != QModbusDevice::ConnectedState) - { - ui->outputWidget->setStatus(tr("Device NOT CONNECTED!")); return; - } const auto dd = displayDefinition(); - if(dd.PointAddress + dd.Length - 1 > ModbusLimits::addressRange().to()) - { - ui->outputWidget->setStatus(tr("Invalid Data Length Specified")); - return; - } - - if(_validSlaveResponses == ui->statisticWidget->validSlaveResposes()) + if(dd.PointAddress + dd.Length - 1 <= ModbusLimits::addressRange().to()) { - _noSlaveResponsesCounter++; - if(_noSlaveResponsesCounter > _modbusClient.numberOfRetries()) + if(_validSlaveResponses == ui->statisticWidget->validSlaveResposes()) { - ui->outputWidget->setStatus(tr("No Responses from Slave Device")); + _noSlaveResponsesCounter++; + if(_noSlaveResponsesCounter > _modbusClient.numberOfRetries()) + { + ui->outputWidget->setStatus(tr("No Responses from Slave Device")); + } } + + _modbusClient.sendReadRequest(dd.PointType, dd.PointAddress - 1, dd.Length, dd.DeviceId, _formId); } +} - _modbusClient.sendReadRequest(dd.PointType, dd.PointAddress - 1, dd.Length, dd.DeviceId, _formId); +/// +/// \brief FormModSca::beginUpdate +/// +void FormModSca::beginUpdate() +{ + if(_modbusClient.state() != QModbusDevice::ConnectedState) + return; + + const auto dd = displayDefinition(); + if(dd.PointAddress + dd.Length - 1 <= ModbusLimits::addressRange().to()) + _modbusClient.sendReadRequest(dd.PointType, dd.PointAddress - 1, dd.Length, dd.DeviceId, _formId); + else + ui->outputWidget->setStatus(tr("No Scan: Invalid Data Length Specified")); + + _timer.start(); } /// @@ -540,6 +552,7 @@ void FormModSca::on_modbusReply(QModbusReply* reply) const auto data = reply->result(); const auto response = reply->rawResult(); + const bool hasError = reply->error() != QModbusDevice::NoError; switch(response.functionCode()) { @@ -547,15 +560,16 @@ void FormModSca::on_modbusReply(QModbusReply* reply) case QModbusRequest::ReadDiscreteInputs: case QModbusRequest::ReadInputRegisters: case QModbusRequest::ReadHoldingRegisters: + ui->outputWidget->updateTraffic(response, reply->serverAddress()); break; default: + ui->outputWidget->updateTraffic(response, reply->serverAddress()); + if(!hasError) beginUpdate(); return; } - ui->outputWidget->updateTraffic(response, reply->serverAddress()); - - if (reply->error() == QModbusDevice::NoError) + if (!hasError) { if(!isValidReply(reply)) { @@ -570,7 +584,9 @@ void FormModSca::on_modbusReply(QModbusReply* reply) } else if (reply->error() == QModbusDevice::ProtocolError) { - ui->outputWidget->setStatus(ModbusException(response.exceptionCode())); + const auto ex = ModbusException(response.exceptionCode()); + const auto errorString = QString("%1 (%2)").arg(ex, formatByteValue(DataDisplayMode::Hex, ex)); + ui->outputWidget->setStatus(errorString); } else { @@ -581,6 +597,23 @@ void FormModSca::on_modbusReply(QModbusReply* reply) _validSlaveResponses = ui->statisticWidget->validSlaveResposes(); } +/// +/// \brief FormModSca::on_modbusConnected +/// +void FormModSca::on_modbusConnected(const ConnectionDetails&) +{ + beginUpdate(); +} + +/// +/// \brief FormModSca::on_modbusDisconnected +/// +void FormModSca::on_modbusDisconnected(const ConnectionDetails&) +{ + _timer.stop(); + ui->outputWidget->setStatus(tr("Device NOT CONNECTED!")); +} + /// /// \brief FormModSca::on_modbusRequest /// \param requestId @@ -599,16 +632,15 @@ void FormModSca::on_modbusRequest(int requestId, const QModbusRequest& request) case QModbusPdu::ReadDiscreteInputs: case QModbusPdu::ReadHoldingRegisters: case QModbusPdu::ReadInputRegisters: - { - const auto deviceId = ui->lineEditDeviceId->value(); - ui->outputWidget->updateTraffic(request, deviceId); ui->statisticWidget->increaseNumberOfPolls(); - } break; - default: + default: break; } + + const auto deviceId = ui->lineEditDeviceId->value(); + ui->outputWidget->updateTraffic(request, deviceId); } /// @@ -618,6 +650,7 @@ void FormModSca::on_lineEditAddress_valueChanged(const QVariant&) { const quint8 deviceId = ui->lineEditDeviceId->value(); ui->outputWidget->setup(displayDefinition(), _dataSimulator->simulationMap(deviceId)); + beginUpdate(); } /// @@ -627,6 +660,7 @@ void FormModSca::on_lineEditLength_valueChanged(const QVariant&) { const quint8 deviceId = ui->lineEditDeviceId->value(); ui->outputWidget->setup(displayDefinition(), _dataSimulator->simulationMap(deviceId)); + beginUpdate(); } /// @@ -636,6 +670,7 @@ void FormModSca::on_lineEditDeviceId_valueChanged(const QVariant&) { const quint8 deviceId = ui->lineEditDeviceId->value(); ui->outputWidget->setup(displayDefinition(), _dataSimulator->simulationMap(deviceId)); + beginUpdate(); } /// @@ -645,6 +680,7 @@ void FormModSca::on_comboBoxModbusPointType_pointTypeChanged(QModbusDataUnit::Re { const quint8 deviceId = ui->lineEditDeviceId->value(); ui->outputWidget->setup(displayDefinition(), _dataSimulator->simulationMap(deviceId)); + beginUpdate(); } /// @@ -675,7 +711,7 @@ void FormModSca::on_outputWidget_itemDoubleClicked(quint16 addr, const QVariant& switch(dlg.exec()) { case QDialog::Accepted: - _modbusClient.writeRegister(pointType, params, 0); + _modbusClient.writeRegister(pointType, params, _formId); break; case 2: @@ -693,7 +729,7 @@ void FormModSca::on_outputWidget_itemDoubleClicked(quint16 addr, const QVariant& { DialogWriteHoldingRegisterBits dlg(params, this); if(dlg.exec() == QDialog::Accepted) - _modbusClient.writeRegister(pointType, params, 0); + _modbusClient.writeRegister(pointType, params, _formId); } else { @@ -701,7 +737,7 @@ void FormModSca::on_outputWidget_itemDoubleClicked(quint16 addr, const QVariant& switch(dlg.exec()) { case QDialog::Accepted: - _modbusClient.writeRegister(pointType, params, 0); + _modbusClient.writeRegister(pointType, params, _formId); break; case 2: diff --git a/omodscan/formmodsca.h b/omodscan/formmodsca.h index f605a60..87a4a6f 100644 --- a/omodscan/formmodsca.h +++ b/omodscan/formmodsca.h @@ -98,6 +98,8 @@ public slots: private slots: void on_timeout(); + void on_modbusConnected(const ConnectionDetails& cd); + void on_modbusDisconnected(const ConnectionDetails& cd); void on_modbusReply(QModbusReply* reply); void on_modbusRequest(int requestId, const QModbusRequest& request); void on_lineEditAddress_valueChanged(const QVariant&); @@ -112,6 +114,7 @@ private slots: void on_dataSimulated(DataDisplayMode mode, QModbusDataUnit::RegisterType type, quint16 addr, quint8 deviceId, QVariant value); private: + void beginUpdate(); bool isValidReply(const QModbusReply* reply); private: @@ -234,6 +237,7 @@ inline QDataStream& operator <<(QDataStream& out, const FormModSca* frm) out << dd.PointType; out << dd.PointAddress; out << dd.Length; + out << dd.LogViewLimit; out << frm->byteOrder(); out << frm->simulationMap(); @@ -251,6 +255,7 @@ inline QDataStream& operator <<(QDataStream& out, const FormModSca* frm) inline QDataStream& operator >>(QDataStream& in, FormModSca* frm) { if(!frm) return in; + const auto ver = frm->property("Version").value(); bool isMaximized; in >> isMaximized; @@ -285,8 +290,10 @@ inline QDataStream& operator >>(QDataStream& in, FormModSca* frm) in >> dd.PointType; in >> dd.PointAddress; in >> dd.Length; - - const auto ver = frm->property("Version").value(); + if(ver >= QVersionNumber(1, 4)) + { + in >> dd.LogViewLimit; + } ByteOrder byteOrder = ByteOrder::LittleEndian; ModbusSimulationMap simulationMap; diff --git a/omodscan/htmldelegate.cpp b/omodscan/htmldelegate.cpp index 4fd7204..2dbb32e 100644 --- a/omodscan/htmldelegate.cpp +++ b/omodscan/htmldelegate.cpp @@ -84,7 +84,9 @@ QSize HtmlDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelInd doc.setHtml(opt.text); doc.setDocumentMargin(0); doc.setDefaultFont(opt.font); - doc.setTextWidth(opt.rect.width()); + + if(opt.features & QStyleOptionViewItem::WrapText) + doc.setTextWidth(opt.rect.width()); return QSize(doc.idealWidth(), doc.size().height()); } diff --git a/omodscan/modbusexception.h b/omodscan/modbusexception.h index f22c6ed..113bcb1 100644 --- a/omodscan/modbusexception.h +++ b/omodscan/modbusexception.h @@ -14,12 +14,12 @@ class ModbusException { } - operator int() + operator int() const { return _code; } - operator QString() + operator QString() const { QString desc; switch (_code) diff --git a/omodscan/modbusfunction.h b/omodscan/modbusfunction.h index 187c383..3c10aa8 100644 --- a/omodscan/modbusfunction.h +++ b/omodscan/modbusfunction.h @@ -19,12 +19,12 @@ class ModbusFunction return _code & QModbusPdu::ExceptionByte; } - operator int() + operator int() const { return _code; } - operator QString() + operator QString() const { QString name; switch(_code & ~QModbusPdu::ExceptionByte) From c2e65d97c1f67603ea8f44e0438bcd3cc255be1f Mon Sep 17 00:00:00 2001 From: sanny32 Date: Fri, 29 Sep 2023 11:30:40 +0300 Subject: [PATCH 13/90] Update version --- omodscan/omodscan.pro | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/omodscan/omodscan.pro b/omodscan/omodscan.pro index deaa8b6..55beb63 100644 --- a/omodscan/omodscan.pro +++ b/omodscan/omodscan.pro @@ -4,7 +4,7 @@ CONFIG += c++17 CONFIG -= debug_and_release CONFIG -= debug_and_release_target -VERSION = 1.5.2 +VERSION = 1.6.0 QMAKE_TARGET_PRODUCT = "Open ModScan" QMAKE_TARGET_DESCRIPTION = "An Open Source Modbus Master (Client) Utility" From 8c0b6a26e94a6f85bb73faa43de3888fee138490 Mon Sep 17 00:00:00 2001 From: sanny32 Date: Fri, 29 Sep 2023 11:50:04 +0300 Subject: [PATCH 14/90] Correct preset multiple regs --- omodscan/dialogs/dialogforcemultipleregisters.cpp | 4 ++-- omodscan/dialogs/dialogsetuppresetdata.cpp | 3 ++- omodscan/formmodsca.cpp | 5 +++-- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/omodscan/dialogs/dialogforcemultipleregisters.cpp b/omodscan/dialogs/dialogforcemultipleregisters.cpp index ef9f71e..5ba46a9 100644 --- a/omodscan/dialogs/dialogforcemultipleregisters.cpp +++ b/omodscan/dialogs/dialogforcemultipleregisters.cpp @@ -270,8 +270,8 @@ NumericLineEdit* DialogForceMultipleRegisters::createNumEdit(int idx) case DataDisplayMode::SwappedUnsignedLI: if(!(idx % 2) && (idx + 1 < _data.size())) { - numEdit = new NumericLineEdit(NumericLineEdit::UnsignedMode, ui->tableWidget); - numEdit->setValue(makeULong(_data[idx + 1], _data[idx], _writeParams.Order)); + numEdit = new NumericLineEdit(NumericLineEdit::UnsignedMode, ui->tableWidget); + numEdit->setValue(makeULong(_data[idx + 1], _data[idx], _writeParams.Order)); } break; diff --git a/omodscan/dialogs/dialogsetuppresetdata.cpp b/omodscan/dialogs/dialogsetuppresetdata.cpp index 7e860af..fa04eb7 100644 --- a/omodscan/dialogs/dialogsetuppresetdata.cpp +++ b/omodscan/dialogs/dialogsetuppresetdata.cpp @@ -16,7 +16,6 @@ DialogSetupPresetData::DialogSetupPresetData(SetupPresetParams& params, QModbus ui->setupUi(this); ui->lineEditSlaveDevice->setInputRange(ModbusLimits::slaveRange()); ui->lineEditAddress->setInputRange(ModbusLimits::addressRange()); - ui->lineEditNumberOfPoints->setInputRange(ModbusLimits::lengthRange()); ui->lineEditSlaveDevice->setValue(params.SlaveAddress); ui->lineEditAddress->setValue(params.PointAddress); ui->lineEditNumberOfPoints->setValue(params.Length); @@ -25,9 +24,11 @@ DialogSetupPresetData::DialogSetupPresetData(SetupPresetParams& params, QModbus { case QModbusDataUnit::Coils: setWindowTitle("15: FORCE MULTIPLE COILS"); + ui->lineEditNumberOfPoints->setInputRange(1, 1968); break; case QModbusDataUnit::HoldingRegisters: setWindowTitle("16: FORCE MULTIPLE REGISTERS"); + ui->lineEditNumberOfPoints->setInputRange(1, 123); break; default: break; diff --git a/omodscan/formmodsca.cpp b/omodscan/formmodsca.cpp index 4aa55b2..496ddf4 100644 --- a/omodscan/formmodsca.cpp +++ b/omodscan/formmodsca.cpp @@ -545,7 +545,8 @@ void FormModSca::on_modbusReply(QModbusReply* reply) { if(!reply) return; - if(_formId != reply->property("RequestId").toInt()) + const auto requestId = reply->property("RequestId").toInt(); + if(_formId != requestId && requestId != 0) { return; } @@ -621,7 +622,7 @@ void FormModSca::on_modbusDisconnected(const ConnectionDetails&) /// void FormModSca::on_modbusRequest(int requestId, const QModbusRequest& request) { - if(requestId != _formId) + if(requestId != _formId && requestId != 0) { return; } From f550c8789440d9ea10b6667566fa80a6dd735270 Mon Sep 17 00:00:00 2001 From: sanny32 Date: Fri, 29 Sep 2023 16:05:33 +0300 Subject: [PATCH 15/90] Refactoring modbus address scan --- omodscan/controls/modbuslogwidget.cpp | 2 +- omodscan/controls/modbusmessagewidget.cpp | 2 +- omodscan/controls/outputwidget.cpp | 6 +- omodscan/controls/outputwidget.h | 2 +- omodscan/dialogs/dialogaddressscan.cpp | 227 +++++++--------------- omodscan/dialogs/dialogaddressscan.h | 77 +++++--- omodscan/formmodsca.cpp | 4 +- omodscan/formmodsca.h | 2 +- omodscan/modbusclient.cpp | 6 +- omodscan/modbusclient.h | 2 +- omodscan/modbusmessages/modbusmessage.h | 63 +++--- 11 files changed, 174 insertions(+), 219 deletions(-) diff --git a/omodscan/controls/modbuslogwidget.cpp b/omodscan/controls/modbuslogwidget.cpp index 4ba2162..36d2d57 100644 --- a/omodscan/controls/modbuslogwidget.cpp +++ b/omodscan/controls/modbuslogwidget.cpp @@ -45,7 +45,7 @@ QVariant ModbusLogModel::data(const QModelIndex& index, int role) const { case Qt::DisplayRole: return QString("%1 %2 %3").arg(item->timestamp().toString(Qt::ISODateWithMs), - (item->isRequest()? "→" : "←"), + (item->isRequest()? "←" : "→"), item->toString(_parentWidget->dataDisplayMode())); case Qt::UserRole: diff --git a/omodscan/controls/modbusmessagewidget.cpp b/omodscan/controls/modbusmessagewidget.cpp index 9e01173..c1a87a0 100644 --- a/omodscan/controls/modbusmessagewidget.cpp +++ b/omodscan/controls/modbusmessagewidget.cpp @@ -347,7 +347,7 @@ void ModbusMessageWidget::update() break; default: - addItem(tr("Data: %1").arg(_msg->data(_dataDisplayMode))); + addItem(tr("Data: %1").arg(formatByteArray(_dataDisplayMode, _msg->rawData()))); break; } } diff --git a/omodscan/controls/outputwidget.cpp b/omodscan/controls/outputwidget.cpp index f8428f6..4812be6 100644 --- a/omodscan/controls/outputwidget.cpp +++ b/omodscan/controls/outputwidget.cpp @@ -595,11 +595,11 @@ void OutputWidget::updateTraffic(const QModbusRequest& request, int server) /// /// \brief OutputWidget::updateTraffic /// \param response -/// \param server +/// \param deviceId /// -void OutputWidget::updateTraffic(const QModbusResponse& response, int server) +void OutputWidget::updateTraffic(const QModbusResponse& response, int deviceId) { - updateLogView(false, server, response); + updateLogView(false, deviceId, response); } /// diff --git a/omodscan/controls/outputwidget.h b/omodscan/controls/outputwidget.h index 51a9998..abd7c97 100644 --- a/omodscan/controls/outputwidget.h +++ b/omodscan/controls/outputwidget.h @@ -135,7 +135,7 @@ private slots: void setUninitializedStatus(); void captureString(const QString& s); void showModbusMessage(const QModelIndex& index); - void updateLogView(bool request, int server, const QModbusPdu& pdu); + void updateLogView(bool request, int deviceId, const QModbusPdu& pdu); private: Ui::OutputWidget *ui; diff --git a/omodscan/dialogs/dialogaddressscan.cpp b/omodscan/dialogs/dialogaddressscan.cpp index 56c72a7..3c581ca 100644 --- a/omodscan/dialogs/dialogaddressscan.cpp +++ b/omodscan/dialogs/dialogaddressscan.cpp @@ -1,81 +1,10 @@ #include #include #include -#include "byteorderutils.h" #include "modbuslimits.h" #include "dialogaddressscan.h" #include "ui_dialogaddressscan.h" -/// -/// \brief formatAddress -/// \param pointType -/// \param address -/// \return -/// -QString formatAddress(QModbusDataUnit::RegisterType pointType, int address) -{ - QString prefix; - switch(pointType) - { - case QModbusDataUnit::Coils: - prefix = "0"; - break; - case QModbusDataUnit::DiscreteInputs: - prefix = "1"; - break; - case QModbusDataUnit::HoldingRegisters: - prefix = "4"; - break; - case QModbusDataUnit::InputRegisters: - prefix = "3"; - break; - default: - break; - } - - return prefix + QStringLiteral("%1").arg(address, 4, 10, QLatin1Char('0')); -} - -/// -/// \brief formatValue -/// \param pointType -/// \param value -/// \param mode -/// \param order -/// \return -/// -QString formatValue(QModbusDataUnit::RegisterType pointType, quint16 value, DataDisplayMode mode, ByteOrder order) -{ - QString result; - value = toByteOrderValue(value, order); - - switch(pointType) - { - case QModbusDataUnit::Coils: - case QModbusDataUnit::DiscreteInputs: - result = QString("%1").arg(value); - break; - case QModbusDataUnit::HoldingRegisters: - case QModbusDataUnit::InputRegisters: - { - switch(mode) - { - case DataDisplayMode::Hex: - result = QStringLiteral("%1H").arg(value, 4, 16, QLatin1Char('0')); - break; - - default: - result = QString("%1").arg(value); - break; - } - } - break; - default: - break; - } - return result.toUpper(); -} - /// /// \brief TableViewItemModel::TableViewItemModel /// \param data @@ -125,12 +54,17 @@ QVariant TableViewItemModel::data(const QModelIndex &index, int role) const switch(role) { case Qt::ToolTipRole: - return formatAddress(_data.registerType(), _data.startAddress() + idx); + return formatAddress(_data.registerType(), _data.startAddress() + idx, false); case Qt::DisplayRole: { - const auto mode = _hexView ? DataDisplayMode::Hex : DataDisplayMode::Decimal; - return _data.hasValue(idx) ? formatValue(_data.registerType(), _data.value(idx), mode, _byteOrder) : "-"; + QVariant outValue; + const auto value = _data.value(idx); + const auto pointType = _data.registerType(); + auto result = _hexView ? formatHexValue(pointType, value, _byteOrder, outValue) : + formatDecimalValue(pointType, value, _byteOrder, outValue); + + return _data.hasValue(idx) ? result.remove('<').remove('>') : "-"; } case Qt::TextAlignmentRole: @@ -207,7 +141,7 @@ QVariant TableViewItemModel::headerData(int section, Qt::Orientation orientation const auto pointAddress = _data.startAddress(); const auto addressFrom = pointAddress + section * _columns; const auto addressTo = pointAddress + qMin(length - 1, (section + 1) * _columns - 1); - return QString("%1-%2").arg(formatAddress(pointType, addressFrom), formatAddress(pointType, addressTo)); + return QString("%1-%2").arg(formatAddress(pointType, addressFrom, false), formatAddress(pointType, addressTo, false)); } } break; @@ -232,33 +166,39 @@ Qt::ItemFlags TableViewItemModel::flags(const QModelIndex &index) const } /// -/// \brief LogViewItemModel::LogViewItemModel -/// \param items +/// \brief LogViewModel::LogViewModel /// \param parent /// -LogViewItemModel::LogViewItemModel(QVector& items, QObject* parent) +LogViewModel::LogViewModel(QObject* parent) : QAbstractListModel(parent) - ,_items(items) { } /// -/// \brief LogViewItemModel::rowCount +/// \brief LogViewModel::~LogViewModel +/// +LogViewModel::~LogViewModel() +{ + void deleteItems(); +} + +/// +/// \brief LogViewModel::rowCount /// \param parent /// \return /// -int LogViewItemModel::rowCount(const QModelIndex&) const +int LogViewModel::rowCount(const QModelIndex&) const { return _items.size(); } /// -/// \brief LogViewItemModel::data +/// \brief LogViewModel::data /// \param index /// \param role /// \return /// -QVariant LogViewItemModel::data(const QModelIndex& index, int role) const +QVariant LogViewModel::data(const QModelIndex& index, int role) const { if(!index.isValid() || index.row() < 0 || @@ -271,13 +211,15 @@ QVariant LogViewItemModel::data(const QModelIndex& index, int role) const switch(role) { case Qt::DisplayRole: - return item.Text; + { + const DataDisplayMode mode = _hexView ? DataDisplayMode::Hex : DataDisplayMode::Decimal; + return QString("[%1] %2 [%3]").arg(formatAddress(item.Msg->pointType(), item.Addr, false), + item.Msg->isRequest() ? "<<" : ">>", + item.Msg->toString(mode)); + } case Qt::BackgroundRole: - return item.IsRequest ? QVariant() : QColor(0xDCDCDC); - - case Qt::TextAlignmentRole: - return Qt::AlignVCenter; + return item.Msg->isRequest() ? QVariant() : QColor(0xDCDCDC); case Qt::UserRole: return QVariant::fromValue(item); @@ -287,26 +229,37 @@ QVariant LogViewItemModel::data(const QModelIndex& index, int role) const } /// -/// \brief LogViewItemProxyModel::LogViewItemProxyModel +/// \brief LogViewModel::deleteItems +/// +void LogViewModel::deleteItems() +{ + for(auto&& i : _items) + delete i.Msg; + + _items.clear(); +} + +/// +/// \brief LogViewProxyModel::LogViewProxyModel /// \param parent /// -LogViewItemProxyModel::LogViewItemProxyModel(QObject* parent) +LogViewProxyModel::LogViewProxyModel(QObject* parent) : QSortFilterProxyModel(parent) ,_showValid(false) { } /// -/// \brief LogViewItemProxyModel::filterAcceptsRow +/// \brief LogViewProxyModel::filterAcceptsRow /// \param source_row /// \param source_parent /// \return /// -bool LogViewItemProxyModel::filterAcceptsRow(int source_row, const QModelIndex &source_parent) const +bool LogViewProxyModel::filterAcceptsRow(int source_row, const QModelIndex &source_parent) const { const auto index = sourceModel()->index(source_row, 0, source_parent); - const auto item = sourceModel()->data(index, Qt::UserRole).value(); - return _showValid ? item.IsValid && !item.IsRequest : true; + const auto msg = sourceModel()->data(index, Qt::UserRole).value(); + return _showValid ? msg->isValid() && !msg->isRequest() && !msg->isException() : true; } /// @@ -339,12 +292,18 @@ DialogAddressScan::DialogAddressScan(const DisplayDefinition& dd, DataDisplayMod ui->checkBoxHexView->setChecked(mode == DataDisplayMode::Hex); ui->comboBoxByteOrder->setCurrentByteOrder(order); + auto proxyLogModel = new LogViewProxyModel(this); + proxyLogModel->setSourceModel(new LogViewModel(this)); + proxyLogModel->setShowValid(ui->checkBoxShowValid->isChecked()); + ui->logView->setModel(proxyLogModel); + auto dispatcher = QAbstractEventDispatcher::instance(); connect(dispatcher, &QAbstractEventDispatcher::awake, this, &DialogAddressScan::on_awake); connect(&_scanTimer, &QTimer::timeout, this, &DialogAddressScan::on_timeout); connect(&_modbusClient, &ModbusClient::modbusReply, this, &DialogAddressScan::on_modbusReply); connect(&_modbusClient, &ModbusClient::modbusRequest, this, &DialogAddressScan::on_modbusRequest); + connect(proxyLogModel->sourceModel(), &LogViewModel::rowsInserted, ui->logView, &QListView::scrollToBottom); clearTableView(); } @@ -403,6 +362,7 @@ void DialogAddressScan::on_checkBoxHexView_toggled(bool on) return; _viewModel->setHexView(on); + ((LogViewProxyModel*)ui->logView->model())->setHexView(on); } /// @@ -410,11 +370,8 @@ void DialogAddressScan::on_checkBoxHexView_toggled(bool on) /// \param on /// void DialogAddressScan::on_checkBoxShowValid_toggled(bool on) -{ - if(!_proxyLogModel) - return; - - _proxyLogModel->setShowValid(on); +{ + ((LogViewProxyModel*)ui->logView->model())->setShowValid(on); } /// @@ -432,16 +389,13 @@ void DialogAddressScan::on_comboBoxByteOrder_byteOrderChanged(ByteOrder order) /// /// \brief DialogAddressScan::on_modbusRequest /// \param requestId +/// \param deviceId /// \param request /// -void DialogAddressScan::on_modbusRequest(int requestId, const QModbusRequest& request) +void DialogAddressScan::on_modbusRequest(int requestId, int deviceId, const QModbusRequest& request) { - if(requestId != -1) - { - return; - } - - updateLogView(request); + if(requestId == -1) + updateLogView(deviceId, request); } /// @@ -585,12 +539,8 @@ void DialogAddressScan::clearTableView() /// void DialogAddressScan::clearLogView() { - _logItems.clear(); - _logModel = QSharedPointer(new LogViewItemModel(_logItems, this)); - _proxyLogModel = QSharedPointer(new LogViewItemProxyModel(this)); - _proxyLogModel->setSourceModel(_logModel.get()); - _proxyLogModel->setShowValid(ui->checkBoxShowValid->isChecked()); - ui->logView->setModel(_proxyLogModel.get()); + auto proxyLogModel = ((LogViewProxyModel*)ui->logView->model()); + proxyLogModel->clear(); } /// @@ -645,36 +595,16 @@ void DialogAddressScan::updateTableView(int pointAddress, QVector value /// /// \brief DialogAddressScan::updateLogView +/// \param deviceId /// \param request /// -void DialogAddressScan::updateLogView(const QModbusRequest& request) +void DialogAddressScan::updateLogView(int deviceId, const QModbusRequest& request) { - const auto deviceId = ui->lineEditSlaveAddress->value(); - const auto pointType = ui->comboBoxPointType->currentPointType(); - quint16 pointAddress; request.decodeData(&pointAddress); - const auto address = formatAddress(pointType, pointAddress + 1); - - QByteArray rawData; - rawData.push_back(deviceId); - rawData.push_back(request.functionCode() | ( request.isException() ? QModbusPdu::ExceptionByte : 0)); - rawData.push_back(request.data()); - QStringList textData; - for(auto&& c : rawData) - textData.append(QString("%1").arg(QString::number((uchar)c), 3, '0')); - - LogViewItem item; - item.IsRequest = true; - item.IsValid = true; - item.PointAddress = pointAddress; - item.Text = QString("[%1] << [%2]").arg(address, textData.join(' ')); - - _logItems.push_back(item); - _logModel->update(); - - ui->logView->scrollTo(_proxyLogModel->index(_logItems.size() - 1, 0), QAbstractItemView::PositionAtBottom); + auto proxyLogModel = ((LogViewProxyModel*)ui->logView->model()); + proxyLogModel->append(pointAddress, ModbusMessage::create(request, QDateTime::currentDateTime(), deviceId, true)); } /// @@ -686,31 +616,12 @@ void DialogAddressScan::updateLogView(const QModbusReply* reply) if(!reply) return; - const auto deviceId = ui->lineEditSlaveAddress->value(); - const auto pointType = ui->comboBoxPointType->currentPointType(); + const auto deviceId = reply->serverAddress(); const auto pointAddress = reply->property("RequestData").value().startAddress() + 1; - const auto address = formatAddress(pointType, pointAddress); const auto pdu = reply->rawResult(); - QByteArray rawData; - rawData.push_back(deviceId); - rawData.push_back(pdu.functionCode() | ( pdu.isException() ? QModbusPdu::ExceptionByte : 0)); - rawData.push_back(pdu.data()); - - QStringList textData; - for(auto&& c : rawData) - textData.append(QString("%1").arg(QString::number((uchar)c), 3, '0')); - - LogViewItem item; - item.IsRequest = false; - item.IsValid = (reply->error() == QModbusDevice::NoError); - item.PointAddress = pointAddress; - item.Text = QString("[%1] >> [%2]").arg(address, textData.join(' ')); - - _logItems.push_back(item); - _logModel->update(); - - ui->logView->scrollTo(_proxyLogModel->index(_logItems.size() - 1, 0), QAbstractItemView::PositionAtBottom); + auto proxyLogModel = ((LogViewProxyModel*)ui->logView->model()); + proxyLogModel->append(pointAddress, ModbusMessage::create(pdu, QDateTime::currentDateTime(), deviceId, false)); } /// diff --git a/omodscan/dialogs/dialogaddressscan.h b/omodscan/dialogs/dialogaddressscan.h index 0d154e8..2462586 100644 --- a/omodscan/dialogs/dialogaddressscan.h +++ b/omodscan/dialogs/dialogaddressscan.h @@ -6,6 +6,7 @@ #include #include #include +#include "modbusmessage.h" #include "modbusdataunit.h" #include "modbusclient.h" #include "displaydefinition.h" @@ -51,50 +52,77 @@ class TableViewItemModel : public QAbstractTableModel }; /// -/// \brief The LogViewItem class +/// \brief The LogViewModel class /// -struct LogViewItem -{ - quint16 PointAddress = 0; - QString Text; - bool IsRequest = false; - bool IsValid = false; -}; -Q_DECLARE_METATYPE(LogViewItem) - -/// -/// \brief The LogViewItemModel class -/// -class LogViewItemModel : public QAbstractListModel +class LogViewModel : public QAbstractListModel { Q_OBJECT public: - explicit LogViewItemModel(QVector& items, QObject* parent = nullptr); + explicit LogViewModel(QObject* parent = nullptr); + ~LogViewModel(); int rowCount(const QModelIndex& parent = QModelIndex()) const override; QVariant data(const QModelIndex& index, int role) const override; - void update(){ + void append(quint16 addr, const ModbusMessage* msg) { + if(msg != nullptr) + { + beginInsertRows(QModelIndex(), rowCount(), rowCount()); + _items.push_back({ addr, msg }); + endInsertRows(); + } + } + + void clear() { + beginResetModel(); + deleteItems(); + endResetModel(); + } + + void setHexView(bool on) { beginResetModel(); + _hexView = on; endResetModel(); } private: - QVector& _items; + void deleteItems(); + +private: + struct LogViewItem{ + quint16 Addr; + const ModbusMessage* Msg; + }; + +private: + bool _hexView = false; + QVector _items; }; /// -/// \brief The LogViewItemProxyModel class +/// \brief The LogViewProxyModel class /// -class LogViewItemProxyModel : public QSortFilterProxyModel +class LogViewProxyModel : public QSortFilterProxyModel { Q_OBJECT public: - explicit LogViewItemProxyModel(QObject* parent = nullptr); + explicit LogViewProxyModel(QObject* parent = nullptr); + + void append(quint16 addr, const ModbusMessage* msg) { + ((LogViewModel*)sourceModel())->append(addr, msg); + } + + void clear() { + ((LogViewModel*)sourceModel())->clear(); + } + + void setHexView(bool on) { + ((LogViewModel*)sourceModel())->setHexView(on); + } - void setShowValid(bool on){ + void setShowValid(bool on) { beginResetModel(); _showValid = on; endResetModel(); @@ -194,7 +222,7 @@ private slots: void on_awake(); void on_timeout(); void on_modbusReply(QModbusReply* reply); - void on_modbusRequest(int requestId, const QModbusRequest& data); + void on_modbusRequest(int requestId, int deviceId, const QModbusRequest& data); void on_checkBoxHexView_toggled(bool); void on_checkBoxShowValid_toggled(bool); void on_comboBoxByteOrder_byteOrderChanged(ByteOrder); @@ -215,7 +243,7 @@ private slots: void updateProgress(); void updateTableView(int pointAddress, QVector values); - void updateLogView(const QModbusRequest& request); + void updateLogView(int deviceId, const QModbusRequest& request); void updateLogView(const QModbusReply* reply); void exportPdf(const QString& filename); @@ -231,9 +259,6 @@ private slots: quint64 _scanTime = 0; QTimer _scanTimer; ModbusClient& _modbusClient; - QVector _logItems; - QSharedPointer _logModel; - QSharedPointer _proxyLogModel; QSharedPointer _viewModel; }; diff --git a/omodscan/formmodsca.cpp b/omodscan/formmodsca.cpp index 496ddf4..54ebfd9 100644 --- a/omodscan/formmodsca.cpp +++ b/omodscan/formmodsca.cpp @@ -618,9 +618,10 @@ void FormModSca::on_modbusDisconnected(const ConnectionDetails&) /// /// \brief FormModSca::on_modbusRequest /// \param requestId +/// \param deviceId /// \param request /// -void FormModSca::on_modbusRequest(int requestId, const QModbusRequest& request) +void FormModSca::on_modbusRequest(int requestId, int deviceId, const QModbusRequest& request) { if(requestId != _formId && requestId != 0) { @@ -640,7 +641,6 @@ void FormModSca::on_modbusRequest(int requestId, const QModbusRequest& request) break; } - const auto deviceId = ui->lineEditDeviceId->value(); ui->outputWidget->updateTraffic(request, deviceId); } diff --git a/omodscan/formmodsca.h b/omodscan/formmodsca.h index 87a4a6f..a02919a 100644 --- a/omodscan/formmodsca.h +++ b/omodscan/formmodsca.h @@ -101,7 +101,7 @@ private slots: void on_modbusConnected(const ConnectionDetails& cd); void on_modbusDisconnected(const ConnectionDetails& cd); void on_modbusReply(QModbusReply* reply); - void on_modbusRequest(int requestId, const QModbusRequest& request); + void on_modbusRequest(int requestId, int deviceId, const QModbusRequest& request); void on_lineEditAddress_valueChanged(const QVariant&); void on_lineEditLength_valueChanged(const QVariant&); void on_lineEditDeviceId_valueChanged(const QVariant&); diff --git a/omodscan/modbusclient.cpp b/omodscan/modbusclient.cpp index f5470ef..c7c1dc4 100644 --- a/omodscan/modbusclient.cpp +++ b/omodscan/modbusclient.cpp @@ -164,7 +164,7 @@ void ModbusClient::sendReadRequest(QModbusDataUnit::RegisterType pointType, int const auto request = createReadRequest(dataUnit); if(!request.isValid()) return; - emit modbusRequest(requestId, request); + emit modbusRequest(requestId, server, request); if(auto reply = _modbusClient->sendReadRequest(dataUnit, server)) { reply->setProperty("RequestId", requestId); @@ -467,7 +467,7 @@ void ModbusClient::writeRegister(QModbusDataUnit::RegisterType pointType, const const auto request = createWriteRequest(data, useMultipleWriteFunc); if(!request.isValid()) return; - emit modbusRequest(requestId, request); + emit modbusRequest(requestId, params.Node, request); if(auto reply = _modbusClient->sendRawRequest(request, params.Node)) { @@ -499,7 +499,7 @@ void ModbusClient::maskWriteRegister(const ModbusMaskWriteParams& params, int re } QModbusRequest request(QModbusRequest::MaskWriteRegister, quint16(params.Address - 1), params.AndMask, params.OrMask); - emit modbusRequest(requestId, request); + emit modbusRequest(requestId, params.Node, request); if(auto reply = _modbusClient->sendRawRequest(request, params.Node)) { diff --git a/omodscan/modbusclient.h b/omodscan/modbusclient.h index 8028abc..482d276 100644 --- a/omodscan/modbusclient.h +++ b/omodscan/modbusclient.h @@ -35,7 +35,7 @@ class ModbusClient : public QObject void maskWriteRegister(const ModbusMaskWriteParams& params, int requestId); signals: - void modbusRequest(int requestId, const QModbusRequest& request); + void modbusRequest(int requestId, int deviceId, const QModbusRequest& request); void modbusReply(QModbusReply* reply); void modbusError(const QString& error, int requestId); void modbusConnectionError(const QString& error); diff --git a/omodscan/modbusmessages/modbusmessage.h b/omodscan/modbusmessages/modbusmessage.h index c0487cd..c9e2a01 100644 --- a/omodscan/modbusmessages/modbusmessage.h +++ b/omodscan/modbusmessages/modbusmessage.h @@ -13,6 +13,23 @@ class ModbusMessage { public: + /// + /// \brief ModbusMessage + /// \param pdu + /// \param timestamp + /// \param deviceId + /// \param request + /// + ModbusMessage(const QModbusPdu& pdu, const QDateTime& timestamp, int deviceId, bool request) + :_data(pdu.data()) + ,_funcCode(pdu.isException() ? (pdu.functionCode() | QModbusPdu::ExceptionByte) : pdu.functionCode()) + ,_exceptionCode(pdu.exceptionCode()) + ,_timestamp(timestamp) + ,_deviceId(deviceId) + ,_request(request) + { + } + /// /// \brief ~ModbusMessage /// @@ -68,6 +85,27 @@ class ModbusMessage return ModbusFunction((QModbusPdu::FunctionCode)_funcCode); } + /// + /// \brief pointType + /// \return + /// + QModbusDataUnit::RegisterType pointType() const { + switch(_funcCode) + { + case QModbusPdu::ReadCoils: + return QModbusDataUnit::Coils; + case QModbusPdu::ReadDiscreteInputs: + return QModbusDataUnit::DiscreteInputs; + case QModbusPdu::ReadHoldingRegisters: + return QModbusDataUnit::HoldingRegisters; + case QModbusPdu::ReadInputRegisters: + return QModbusDataUnit::InputRegisters; + + default: + return QModbusDataUnit::Invalid; + } + } + /// /// \brief isException /// \return @@ -98,31 +136,12 @@ class ModbusMessage } /// - /// \brief data - /// \param mode + /// \brief rawData /// \return /// - QString data(DataDisplayMode mode) const - { - return formatByteArray(mode, _data); - } - -protected: - /// - /// \brief ModbusMessage - /// \param pdu - /// \param timestamp - /// \param deviceId - /// \param request - /// - ModbusMessage(const QModbusPdu& pdu, const QDateTime& timestamp, int deviceId, bool request) - :_data(pdu.data()) - ,_funcCode(pdu.isException() ? (pdu.functionCode() | QModbusPdu::ExceptionByte) : pdu.functionCode()) - ,_exceptionCode(pdu.exceptionCode()) - ,_timestamp(timestamp) - ,_deviceId(deviceId) - ,_request(request) + QByteArray rawData() const { + return _data; } protected: From 6deedb976812f924536e037ca00f6ea18eff34ab Mon Sep 17 00:00:00 2001 From: sanny32 Date: Fri, 29 Sep 2023 16:16:05 +0300 Subject: [PATCH 16/90] Refactoring modbus address scan --- omodscan/dialogs/dialogaddressscan.cpp | 11 +++++++---- omodscan/dialogs/dialogaddressscan.h | 16 ++++++++++------ omodscan/modbusmessages/modbusmessage.h | 21 --------------------- 3 files changed, 17 insertions(+), 31 deletions(-) diff --git a/omodscan/dialogs/dialogaddressscan.cpp b/omodscan/dialogs/dialogaddressscan.cpp index 3c581ca..6b15511 100644 --- a/omodscan/dialogs/dialogaddressscan.cpp +++ b/omodscan/dialogs/dialogaddressscan.cpp @@ -213,7 +213,7 @@ QVariant LogViewModel::data(const QModelIndex& index, int role) const case Qt::DisplayRole: { const DataDisplayMode mode = _hexView ? DataDisplayMode::Hex : DataDisplayMode::Decimal; - return QString("[%1] %2 [%3]").arg(formatAddress(item.Msg->pointType(), item.Addr, false), + return QString("[%1] %2 [%3]").arg(formatAddress(item.Type, item.Addr, false), item.Msg->isRequest() ? "<<" : ">>", item.Msg->toString(mode)); } @@ -222,7 +222,7 @@ QVariant LogViewModel::data(const QModelIndex& index, int role) const return item.Msg->isRequest() ? QVariant() : QColor(0xDCDCDC); case Qt::UserRole: - return QVariant::fromValue(item); + return QVariant::fromValue(item.Msg); } return QVariant(); @@ -295,6 +295,7 @@ DialogAddressScan::DialogAddressScan(const DisplayDefinition& dd, DataDisplayMod auto proxyLogModel = new LogViewProxyModel(this); proxyLogModel->setSourceModel(new LogViewModel(this)); proxyLogModel->setShowValid(ui->checkBoxShowValid->isChecked()); + proxyLogModel->setHexView(ui->checkBoxHexView->isChecked()); ui->logView->setModel(proxyLogModel); auto dispatcher = QAbstractEventDispatcher::instance(); @@ -604,7 +605,8 @@ void DialogAddressScan::updateLogView(int deviceId, const QModbusRequest& reques request.decodeData(&pointAddress); auto proxyLogModel = ((LogViewProxyModel*)ui->logView->model()); - proxyLogModel->append(pointAddress, ModbusMessage::create(request, QDateTime::currentDateTime(), deviceId, true)); + proxyLogModel->append(pointAddress, ui->comboBoxPointType->currentPointType(), + ModbusMessage::create(request, QDateTime::currentDateTime(), deviceId, true)); } /// @@ -621,7 +623,8 @@ void DialogAddressScan::updateLogView(const QModbusReply* reply) const auto pdu = reply->rawResult(); auto proxyLogModel = ((LogViewProxyModel*)ui->logView->model()); - proxyLogModel->append(pointAddress, ModbusMessage::create(pdu, QDateTime::currentDateTime(), deviceId, false)); + proxyLogModel->append(pointAddress, ui->comboBoxPointType->currentPointType(), + ModbusMessage::create(pdu, QDateTime::currentDateTime(), deviceId, false)); } /// diff --git a/omodscan/dialogs/dialogaddressscan.h b/omodscan/dialogs/dialogaddressscan.h index 2462586..cb90616 100644 --- a/omodscan/dialogs/dialogaddressscan.h +++ b/omodscan/dialogs/dialogaddressscan.h @@ -65,11 +65,11 @@ class LogViewModel : public QAbstractListModel int rowCount(const QModelIndex& parent = QModelIndex()) const override; QVariant data(const QModelIndex& index, int role) const override; - void append(quint16 addr, const ModbusMessage* msg) { + void append(quint16 addr, QModbusDataUnit::RegisterType type, const ModbusMessage* msg) { if(msg != nullptr) { beginInsertRows(QModelIndex(), rowCount(), rowCount()); - _items.push_back({ addr, msg }); + _items.push_back({ addr, type, msg }); endInsertRows(); } } @@ -92,6 +92,7 @@ class LogViewModel : public QAbstractListModel private: struct LogViewItem{ quint16 Addr; + QModbusDataUnit::RegisterType Type; const ModbusMessage* Msg; }; @@ -110,16 +111,19 @@ class LogViewProxyModel : public QSortFilterProxyModel public: explicit LogViewProxyModel(QObject* parent = nullptr); - void append(quint16 addr, const ModbusMessage* msg) { - ((LogViewModel*)sourceModel())->append(addr, msg); + void append(quint16 addr, QModbusDataUnit::RegisterType type, const ModbusMessage* msg) { + if(sourceModel()) + ((LogViewModel*)sourceModel())->append(addr, type, msg); } void clear() { - ((LogViewModel*)sourceModel())->clear(); + if(sourceModel()) + ((LogViewModel*)sourceModel())->clear(); } void setHexView(bool on) { - ((LogViewModel*)sourceModel())->setHexView(on); + if(sourceModel()) + ((LogViewModel*)sourceModel())->setHexView(on); } void setShowValid(bool on) { diff --git a/omodscan/modbusmessages/modbusmessage.h b/omodscan/modbusmessages/modbusmessage.h index c9e2a01..0405417 100644 --- a/omodscan/modbusmessages/modbusmessage.h +++ b/omodscan/modbusmessages/modbusmessage.h @@ -85,27 +85,6 @@ class ModbusMessage return ModbusFunction((QModbusPdu::FunctionCode)_funcCode); } - /// - /// \brief pointType - /// \return - /// - QModbusDataUnit::RegisterType pointType() const { - switch(_funcCode) - { - case QModbusPdu::ReadCoils: - return QModbusDataUnit::Coils; - case QModbusPdu::ReadDiscreteInputs: - return QModbusDataUnit::DiscreteInputs; - case QModbusPdu::ReadHoldingRegisters: - return QModbusDataUnit::HoldingRegisters; - case QModbusPdu::ReadInputRegisters: - return QModbusDataUnit::InputRegisters; - - default: - return QModbusDataUnit::Invalid; - } - } - /// /// \brief isException /// \return From 8f5910b391c6695a17a02b83c91f491ab0bba32b Mon Sep 17 00:00:00 2001 From: sanny32 Date: Mon, 2 Oct 2023 10:32:25 +0300 Subject: [PATCH 17/90] Refactoring --- omodscan/dialogs/dialogaddressscan.h | 10 +- omodscan/dialogs/dialogforcemultiplecoils.cpp | 12 +- omodscan/dialogs/dialogforcemultiplecoils.ui | 98 +++++++++------ .../dialogs/dialogforcemultipleregisters.cpp | 12 +- .../dialogs/dialogforcemultipleregisters.h | 1 + .../dialogs/dialogforcemultipleregisters.ui | 117 ++++++++++++------ omodscan/formmodsca.cpp | 6 +- omodscan/mainwindow.cpp | 4 +- 8 files changed, 165 insertions(+), 95 deletions(-) diff --git a/omodscan/dialogs/dialogaddressscan.h b/omodscan/dialogs/dialogaddressscan.h index cb90616..a671426 100644 --- a/omodscan/dialogs/dialogaddressscan.h +++ b/omodscan/dialogs/dialogaddressscan.h @@ -66,12 +66,10 @@ class LogViewModel : public QAbstractListModel QVariant data(const QModelIndex& index, int role) const override; void append(quint16 addr, QModbusDataUnit::RegisterType type, const ModbusMessage* msg) { - if(msg != nullptr) - { - beginInsertRows(QModelIndex(), rowCount(), rowCount()); - _items.push_back({ addr, type, msg }); - endInsertRows(); - } + if(msg == nullptr) return; + beginInsertRows(QModelIndex(), rowCount(), rowCount()); + _items.push_back({ addr, type, msg }); + endInsertRows(); } void clear() { diff --git a/omodscan/dialogs/dialogforcemultiplecoils.cpp b/omodscan/dialogs/dialogforcemultiplecoils.cpp index b2013fd..38ce387 100644 --- a/omodscan/dialogs/dialogforcemultiplecoils.cpp +++ b/omodscan/dialogs/dialogforcemultiplecoils.cpp @@ -1,5 +1,6 @@ #include #include +#include "formatutils.h" #include "dialogforcemultiplecoils.h" #include "ui_dialogforcemultiplecoils.h" @@ -18,8 +19,9 @@ DialogForceMultipleCoils::DialogForceMultipleCoils(ModbusWriteParams& params, in Qt::CustomizeWindowHint | Qt::WindowTitleHint); - ui->labelAddress->setText(QString(tr("Address: %1")).arg(params.Address, 5, 10, QLatin1Char('0'))); - ui->labelLength->setText(QString(tr("Length: %1")).arg(length, 3, 10, QLatin1Char('0'))); + ui->labelAddress->setText(QString(tr("Address: %1")).arg(formatAddress(QModbusDataUnit::Coils, params.Address, false))); + ui->labelLength->setText(QString(tr("Length: %1")).arg(length, 3, 10, QLatin1Char('0'))); + ui->labelSlaveDevice->setText(QString(tr("Slave Device: %1")).arg(params.Node, 2, 10, QLatin1Char('0'))); _data = params.Value.value>(); if(_data.length() != length) _data.resize(length); @@ -107,8 +109,8 @@ void DialogForceMultipleCoils::updateTableWidget() for(int i = 0; i < ui->tableWidget->rowCount(); i++) { - const auto addressFrom = QString("%1").arg(_writeParams.Address + i * columns, 5, 10, QLatin1Char('0')); - const auto addressTo = QString("%1").arg(_writeParams.Address + qMin(length - 1, (i + 1) * columns - 1), 5, 10, QLatin1Char('0')); + const auto addressFrom = formatAddress(QModbusDataUnit::Coils, _writeParams.Address + i * columns, false); + const auto addressTo = formatAddress(QModbusDataUnit::Coils, _writeParams.Address + qMin(length - 1, (i + 1) * columns - 1), false); ui->tableWidget->setVerticalHeaderItem(i, new QTableWidgetItem(QString("%1-%2").arg(addressFrom, addressTo))); for(int j = 0; j < columns; j++) @@ -119,7 +121,7 @@ void DialogForceMultipleCoils::updateTableWidget() auto item = new QTableWidgetItem(QString::number(_data[idx])); item->setData(Qt::UserRole, idx); item->setTextAlignment(Qt::AlignCenter); - item->setToolTip(QString("%1").arg(_writeParams.Address + idx, 5, 10, QLatin1Char('0'))); + item->setToolTip(formatAddress(QModbusDataUnit::Coils,_writeParams.Address + idx, false)); ui->tableWidget->setItem(i, j, item); } else diff --git a/omodscan/dialogs/dialogforcemultiplecoils.ui b/omodscan/dialogs/dialogforcemultiplecoils.ui index fe44177..88723ba 100644 --- a/omodscan/dialogs/dialogforcemultiplecoils.ui +++ b/omodscan/dialogs/dialogforcemultiplecoils.ui @@ -22,14 +22,69 @@ - - - - Address: + + + + Qt::Horizontal - + + + 40 + 20 + + + + + + + + + + Slave Device: + + + + + + + Address: + + + Qt::AlignCenter + + + + + + + Length: + + + Qt::AlignCenter + + + + - + + + + + + Set Values to 0 + + + + + + + Set Values to 1 + + + + + + Qt::NoFocus @@ -63,38 +118,11 @@ - - + + Qt::Horizontal - - - 40 - 20 - - - - - - - - Set Values to 0 - - - - - - - Set Values to 1 - - - - - - - Length: - diff --git a/omodscan/dialogs/dialogforcemultipleregisters.cpp b/omodscan/dialogs/dialogforcemultipleregisters.cpp index 5ba46a9..d5ef0fa 100644 --- a/omodscan/dialogs/dialogforcemultipleregisters.cpp +++ b/omodscan/dialogs/dialogforcemultipleregisters.cpp @@ -1,5 +1,6 @@ #include #include +#include "formatutils.h" #include "numericutils.h" #include "numericlineedit.h" #include "dialogforcemultipleregisters.h" @@ -21,8 +22,9 @@ DialogForceMultipleRegisters::DialogForceMultipleRegisters(ModbusWriteParams& pa Qt::CustomizeWindowHint | Qt::WindowTitleHint); - ui->labelAddress->setText(QString(tr("Address: %1")).arg(params.Address, 5, 10, QLatin1Char('0'))); - ui->labelLength->setText(QString(tr("Length: %1")).arg(length, 3, 10, QLatin1Char('0'))); + ui->labelAddress->setText(QString(tr("Address: %1")).arg(formatAddress(QModbusDataUnit::HoldingRegisters, params.Address, _hexView))); + ui->labelLength->setText(QString(tr("Length: %1")).arg(length, 3, 10, QLatin1Char('0'))); + ui->labelSlaveDevice->setText(QString(tr("Slave Device: %1")).arg(params.Node, 2, 10, QLatin1Char('0'))); _data = params.Value.value>(); if(_data.length() != length) _data.resize(length); @@ -313,7 +315,7 @@ NumericLineEdit* DialogForceMultipleRegisters::createNumEdit(int idx) numEdit->setFrame(false); numEdit->setMaximumWidth(80); numEdit->setAlignment(Qt::AlignCenter); - numEdit->setToolTip(QString("%1").arg(_writeParams.Address + idx, 5, 10, QLatin1Char('0'))); + numEdit->setToolTip(formatAddress(QModbusDataUnit::HoldingRegisters, _writeParams.Address + idx, _hexView)); } return numEdit; @@ -354,8 +356,8 @@ void DialogForceMultipleRegisters::updateTableWidget() for(int i = 0; i < ui->tableWidget->rowCount(); i++) { - const auto addressFrom = QString("%1").arg(_writeParams.Address + i * columns, 5, 10, QLatin1Char('0')); - const auto addressTo = QString("%1").arg(_writeParams.Address + qMin(length - 1, (i + 1) * columns - 1), 5, 10, QLatin1Char('0')); + const auto addressFrom = formatAddress(QModbusDataUnit::HoldingRegisters, _writeParams.Address + i * columns, _hexView); + const auto addressTo = formatAddress(QModbusDataUnit::HoldingRegisters, _writeParams.Address + qMin(length - 1, (i + 1) * columns - 1), _hexView); ui->tableWidget->setVerticalHeaderItem(i, new QTableWidgetItem(QString("%1-%2").arg(addressFrom, addressTo))); for(int j = 0; j < columns; j++) diff --git a/omodscan/dialogs/dialogforcemultipleregisters.h b/omodscan/dialogs/dialogforcemultipleregisters.h index 2ea7cb2..8ea3c86 100644 --- a/omodscan/dialogs/dialogforcemultipleregisters.h +++ b/omodscan/dialogs/dialogforcemultipleregisters.h @@ -36,6 +36,7 @@ private slots: Ui::DialogForceMultipleRegisters *ui; QVector _data; ModbusWriteParams& _writeParams; + bool _hexView = false; }; #endif // DIALOGFORCEMULTIPLEREGISTERS_H diff --git a/omodscan/dialogs/dialogforcemultipleregisters.ui b/omodscan/dialogs/dialogforcemultipleregisters.ui index b8740c1..0ce920b 100644 --- a/omodscan/dialogs/dialogforcemultipleregisters.ui +++ b/omodscan/dialogs/dialogforcemultipleregisters.ui @@ -22,48 +22,35 @@ - - - - Length: + + + + 10 - - - - - - Set Random Values - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - Set Values to 0 - - - - - - - Address: - - + + + + Slave Device: + + + + + + + Address: + + + + + + + Length: + + + + - + Qt::NoFocus @@ -97,6 +84,56 @@ + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + 0 + 0 + + + + Set Values to 0 + + + + + + + + 0 + 0 + + + + Set Random Values + + + + + + + + + Qt::Horizontal + + + diff --git a/omodscan/formmodsca.cpp b/omodscan/formmodsca.cpp index 54ebfd9..094a0cf 100644 --- a/omodscan/formmodsca.cpp +++ b/omodscan/formmodsca.cpp @@ -546,7 +546,8 @@ void FormModSca::on_modbusReply(QModbusReply* reply) if(!reply) return; const auto requestId = reply->property("RequestId").toInt(); - if(_formId != requestId && requestId != 0) + if((_formId != requestId && requestId != 0) || + reply->serverAddress() != ui->lineEditDeviceId->value()) { return; } @@ -623,7 +624,8 @@ void FormModSca::on_modbusDisconnected(const ConnectionDetails&) /// void FormModSca::on_modbusRequest(int requestId, int deviceId, const QModbusRequest& request) { - if(requestId != _formId && requestId != 0) + if((requestId != _formId && requestId != 0) || + deviceId != ui->lineEditDeviceId->value()) { return; } diff --git a/omodscan/mainwindow.cpp b/omodscan/mainwindow.cpp index 6356cd4..91ac483 100644 --- a/omodscan/mainwindow.cpp +++ b/omodscan/mainwindow.cpp @@ -634,7 +634,7 @@ void MainWindow::on_actionForceCoils_triggered() params.Node = presetParams.SlaveAddress; params.Address = presetParams.PointAddress; - if(dd.PointType == QModbusDataUnit::Coils) + if(dd.PointType == QModbusDataUnit::Coils && dd.DeviceId == params.Node) { params.Value = QVariant::fromValue(frm->data()); } @@ -668,7 +668,7 @@ void MainWindow::on_actionPresetRegs_triggered() params.DisplayMode = frm->dataDisplayMode(); params.Order = frm->byteOrder(); - if(dd.PointType == QModbusDataUnit::HoldingRegisters) + if(dd.PointType == QModbusDataUnit::HoldingRegisters && dd.DeviceId == params.Node) { params.Value = QVariant::fromValue(frm->data()); } From 7d7bc5b2726f5714309267a0855e4ae42a077bf8 Mon Sep 17 00:00:00 2001 From: sanny32 Date: Mon, 2 Oct 2023 11:24:13 +0300 Subject: [PATCH 18/90] Refactoring --- omodscan/dialogs/dialogaddressscan.cpp | 56 ++++++++++---------------- omodscan/dialogs/dialogaddressscan.h | 20 +++++---- omodscan/mainwindow.cpp | 8 +++- 3 files changed, 41 insertions(+), 43 deletions(-) diff --git a/omodscan/dialogs/dialogaddressscan.cpp b/omodscan/dialogs/dialogaddressscan.cpp index 6b15511..215069c 100644 --- a/omodscan/dialogs/dialogaddressscan.cpp +++ b/omodscan/dialogs/dialogaddressscan.cpp @@ -7,14 +7,10 @@ /// /// \brief TableViewItemModel::TableViewItemModel -/// \param data -/// \param columns /// \param parent /// -TableViewItemModel::TableViewItemModel(const ModbusDataUnit& data, int columns, QObject* parent) +TableViewItemModel::TableViewItemModel(QObject* parent) : QAbstractTableModel(parent) - ,_columns(columns) - ,_data(data) { } @@ -280,6 +276,13 @@ DialogAddressScan::DialogAddressScan(const DisplayDefinition& dd, DataDisplayMod Qt::WindowCloseButtonHint | Qt::WindowMaximizeButtonHint); + auto viewModel = new TableViewItemModel(this); + ui->tableView->setModel(viewModel); + + auto proxyLogModel = new LogViewProxyModel(this); + proxyLogModel->setSourceModel(new LogViewModel(this)); + ui->logView->setModel(proxyLogModel); + ui->comboBoxPointType->setCurrentPointType(dd.PointType); ui->lineEditStartAddress->setPaddingZeroes(true); ui->lineEditStartAddress->setInputRange(ModbusLimits::addressRange()); @@ -292,12 +295,6 @@ DialogAddressScan::DialogAddressScan(const DisplayDefinition& dd, DataDisplayMod ui->checkBoxHexView->setChecked(mode == DataDisplayMode::Hex); ui->comboBoxByteOrder->setCurrentByteOrder(order); - auto proxyLogModel = new LogViewProxyModel(this); - proxyLogModel->setSourceModel(new LogViewModel(this)); - proxyLogModel->setShowValid(ui->checkBoxShowValid->isChecked()); - proxyLogModel->setHexView(ui->checkBoxHexView->isChecked()); - ui->logView->setModel(proxyLogModel); - auto dispatcher = QAbstractEventDispatcher::instance(); connect(dispatcher, &QAbstractEventDispatcher::awake, this, &DialogAddressScan::on_awake); @@ -358,11 +355,8 @@ void DialogAddressScan::on_timeout() /// \param on /// void DialogAddressScan::on_checkBoxHexView_toggled(bool on) -{ - if(!_viewModel) - return; - - _viewModel->setHexView(on); +{ + ((TableViewItemModel*)ui->tableView->model())->setHexView(on); ((LogViewProxyModel*)ui->logView->model())->setHexView(on); } @@ -381,10 +375,7 @@ void DialogAddressScan::on_checkBoxShowValid_toggled(bool on) /// void DialogAddressScan::on_comboBoxByteOrder_byteOrderChanged(ByteOrder order) { - if(!_viewModel) - return; - - _viewModel->setByteOrder(order); + ((TableViewItemModel*)ui->tableView->model())->setByteOrder(order); } /// @@ -524,10 +515,7 @@ void DialogAddressScan::clearTableView() const auto pointAddress = ui->lineEditStartAddress->value(); ModbusDataUnit data(pointType, pointAddress, length); - _viewModel = QSharedPointer(new TableViewItemModel(data, 10, this)); - _viewModel->setHexView(ui->checkBoxHexView->isChecked()); - _viewModel->setByteOrder(ui->comboBoxByteOrder->currentByteOrder()); - ui->tableView->setModel(_viewModel.get()); + ((TableViewItemModel*)ui->tableView->model())->reset(data); ui->tableView->resizeColumnsToContents(); ui->tableView->horizontalHeader()->setMinimumSectionSize(80); @@ -579,15 +567,15 @@ void DialogAddressScan::updateProgress() /// void DialogAddressScan::updateTableView(int pointAddress, QVector values) { - if(!_viewModel) return; - for(int i = 0; i < _viewModel->rowCount(); i++) + auto model = ui->tableView->model(); + for(int i = 0; i < model->rowCount(); i++) { - for(int j = 0; j < _viewModel->columnCount(); j++) + for(int j = 0; j < model->columnCount(); j++) { - const auto index = _viewModel->index(i, j); - if(_viewModel->data(index, Qt::UserRole).toInt() == pointAddress) + const auto index = model->index(i, j); + if(model->data(index, Qt::UserRole).toInt() == pointAddress) { - _viewModel->setData(index, QVariant::fromValue(values), Qt::DisplayRole); + model->setData(index, QVariant::fromValue(values), Qt::DisplayRole); return; } } @@ -633,7 +621,7 @@ void DialogAddressScan::updateLogView(const QModbusReply* reply) /// void DialogAddressScan::exportPdf(const QString& filename) { - PdfExporter exporter(_viewModel.get(), + PdfExporter exporter(ui->tableView->model(), ui->lineEditStartAddress->text(), ui->lineEditLength->text(), ui->lineEditSlaveAddress->text(), @@ -650,7 +638,7 @@ void DialogAddressScan::exportPdf(const QString& filename) /// void DialogAddressScan::exportCsv(const QString& filename) { - CsvExporter exporter(_viewModel.get(), + CsvExporter exporter(ui->tableView->model(), ui->lineEditStartAddress->text(), ui->lineEditLength->text(), ui->lineEditSlaveAddress->text(), @@ -670,7 +658,7 @@ void DialogAddressScan::exportCsv(const QString& filename) /// \param pointType /// \param parent /// -PdfExporter::PdfExporter(QAbstractTableModel* model, +PdfExporter::PdfExporter(QAbstractItemModel* model, const QString& startAddress, const QString& length, const QString& devId, @@ -906,7 +894,7 @@ void PdfExporter::paintVLine(int top, int bottom, QPainter& painter) /// \param regsOnQuery /// \param parent /// -CsvExporter::CsvExporter(QAbstractTableModel* model, +CsvExporter::CsvExporter(QAbstractItemModel* model, const QString& startAddress, const QString& length, const QString& devId, diff --git a/omodscan/dialogs/dialogaddressscan.h b/omodscan/dialogs/dialogaddressscan.h index a671426..052fa1b 100644 --- a/omodscan/dialogs/dialogaddressscan.h +++ b/omodscan/dialogs/dialogaddressscan.h @@ -23,7 +23,7 @@ class TableViewItemModel : public QAbstractTableModel Q_OBJECT public: - explicit TableViewItemModel(const ModbusDataUnit& data, int columns, QObject* parent = nullptr); + explicit TableViewItemModel(QObject* parent = nullptr); int rowCount(const QModelIndex& parent = QModelIndex()) const override; int columnCount(const QModelIndex& parent = QModelIndex()) const override; @@ -32,6 +32,13 @@ class TableViewItemModel : public QAbstractTableModel QVariant headerData(int section, Qt::Orientation orientation, int role) const override; Qt::ItemFlags flags(const QModelIndex& index) const override; + void reset(const ModbusDataUnit& data, int columns = 10){ + beginResetModel(); + _columns = columns; + _data = data; + endResetModel(); + } + void setHexView(bool on){ beginResetModel(); _hexView = on; @@ -45,7 +52,7 @@ class TableViewItemModel : public QAbstractTableModel } private: - int _columns; + int _columns = 10; ModbusDataUnit _data; bool _hexView = false; ByteOrder _byteOrder = ByteOrder::LittleEndian; @@ -145,7 +152,7 @@ class PdfExporter : public QObject Q_OBJECT public: - explicit PdfExporter(QAbstractTableModel* model, + explicit PdfExporter(QAbstractItemModel* model, const QString& startAddress, const QString& length, const QString& devId, @@ -171,7 +178,7 @@ class PdfExporter : public QObject const int _cy = 4; const int _cx = 10; QRect _pageRect; - QAbstractTableModel* _model; + QAbstractItemModel* _model; const QString _startAddress; const QString _length; const QString _deviceId; @@ -188,7 +195,7 @@ class CsvExporter: public QObject Q_OBJECT public: - explicit CsvExporter(QAbstractTableModel* model, + explicit CsvExporter(QAbstractItemModel* model, const QString& startAddress, const QString& length, const QString& devId, @@ -198,7 +205,7 @@ class CsvExporter: public QObject void exportCsv(const QString& filename); private: - QAbstractTableModel* _model; + QAbstractItemModel* _model; const QString _startAddress; const QString _length; const QString _deviceId; @@ -261,7 +268,6 @@ private slots: quint64 _scanTime = 0; QTimer _scanTimer; ModbusClient& _modbusClient; - QSharedPointer _viewModel; }; #endif // DIALOGADDRESSSCAN_H diff --git a/omodscan/mainwindow.cpp b/omodscan/mainwindow.cpp index 91ac483..c4c91bd 100644 --- a/omodscan/mainwindow.cpp +++ b/omodscan/mainwindow.cpp @@ -634,7 +634,9 @@ void MainWindow::on_actionForceCoils_triggered() params.Node = presetParams.SlaveAddress; params.Address = presetParams.PointAddress; - if(dd.PointType == QModbusDataUnit::Coils && dd.DeviceId == params.Node) + if(dd.PointType == QModbusDataUnit::Coils && + dd.DeviceId == params.Node && + dd.PointAddress == params.Address) { params.Value = QVariant::fromValue(frm->data()); } @@ -668,7 +670,9 @@ void MainWindow::on_actionPresetRegs_triggered() params.DisplayMode = frm->dataDisplayMode(); params.Order = frm->byteOrder(); - if(dd.PointType == QModbusDataUnit::HoldingRegisters && dd.DeviceId == params.Node) + if(dd.PointType == QModbusDataUnit::HoldingRegisters && + dd.DeviceId == params.Node && + dd.PointAddress == params.Address) { params.Value = QVariant::fromValue(frm->data()); } From c5ebe88d77a8c8bf5393de4a60c92691b070a353 Mon Sep 17 00:00:00 2001 From: sanny32 Date: Mon, 2 Oct 2023 13:58:48 +0300 Subject: [PATCH 19/90] fixed bug with QModbusDevice::InvalidResponseError when use QModbusRequest::MaskWriteRegister function --- omodscan/modbusclient.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/omodscan/modbusclient.cpp b/omodscan/modbusclient.cpp index c7c1dc4..f9ca2be 100644 --- a/omodscan/modbusclient.cpp +++ b/omodscan/modbusclient.cpp @@ -629,6 +629,10 @@ void ModbusClient::on_writeReply() break; case QModbusRequest::MaskWriteRegister: + #if QT_VERSION >= QT_VERSION_CHECK(6, 4, 0) + if(reply->error() == QModbusDevice::InvalidResponseError) + break; + #endif onError(tr("Mask Register Write Failure"), requestId); break; From 2ebc6d3b67c724fcda720489c5d08129d26c2827 Mon Sep 17 00:00:00 2001 From: sanny32 Date: Mon, 2 Oct 2023 13:59:06 +0300 Subject: [PATCH 20/90] Correct max Scan Rate --- omodscan/displaydefinition.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/omodscan/displaydefinition.h b/omodscan/displaydefinition.h index f3798db..ca0208c 100644 --- a/omodscan/displaydefinition.h +++ b/omodscan/displaydefinition.h @@ -19,7 +19,7 @@ struct DisplayDefinition void normalize() { - ScanRate = qBound(20U, ScanRate, 10000U); + ScanRate = qBound(20U, ScanRate, 3600000U); DeviceId = qMax(ModbusLimits::slaveRange().from(), DeviceId); PointAddress = qMax(ModbusLimits::addressRange().from(), PointAddress); PointType = qBound(QModbusDataUnit::DiscreteInputs, PointType, QModbusDataUnit::HoldingRegisters); From 4604538a3aa127be0000ed89760c4f6511097082 Mon Sep 17 00:00:00 2001 From: sanny32 Date: Mon, 2 Oct 2023 13:59:27 +0300 Subject: [PATCH 21/90] Correct show MaskWrite dialog --- omodscan/mainwindow.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/omodscan/mainwindow.cpp b/omodscan/mainwindow.cpp index c4c91bd..895f9a0 100644 --- a/omodscan/mainwindow.cpp +++ b/omodscan/mainwindow.cpp @@ -689,7 +689,12 @@ void MainWindow::on_actionPresetRegs_triggered() /// void MainWindow::on_actionMaskWrite_triggered() { - ModbusMaskWriteParams params = { 1, 1, 0xFFFF, 0}; + auto frm = currentMdiChild(); + if(!frm) return; + + const auto dd = frm->displayDefinition(); + ModbusMaskWriteParams params = { dd.DeviceId, dd.PointAddress, 0xFFFF, 0}; + DialogMaskWriteRegiter dlg(params, this); if(dlg.exec() == QDialog::Accepted) { From 6b742ee7f318b5459d350a8fd697b5f6459b8f82 Mon Sep 17 00:00:00 2001 From: sanny32 Date: Mon, 2 Oct 2023 15:44:15 +0300 Subject: [PATCH 22/90] Correct absent of 'break' word --- omodscan/modbusfunction.h | 1 + 1 file changed, 1 insertion(+) diff --git a/omodscan/modbusfunction.h b/omodscan/modbusfunction.h index 3c10aa8..f98c0c9 100644 --- a/omodscan/modbusfunction.h +++ b/omodscan/modbusfunction.h @@ -59,6 +59,7 @@ class ModbusFunction case QModbusPdu::Diagnostics: name = "DIAGNOSTICS"; + break; case QModbusPdu::GetCommEventCounter: name = "GET COMM EVENT CNT"; From a15d292ebd26496f5945ff2c7088812854d4b9f3 Mon Sep 17 00:00:00 2001 From: sanny32 Date: Mon, 2 Oct 2023 15:44:22 +0300 Subject: [PATCH 23/90] Refactoring --- omodscan/modbusclient.cpp | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/omodscan/modbusclient.cpp b/omodscan/modbusclient.cpp index f9ca2be..a0d0ec1 100644 --- a/omodscan/modbusclient.cpp +++ b/omodscan/modbusclient.cpp @@ -601,9 +601,20 @@ void ModbusClient::on_writeReply() auto reply = qobject_cast(sender()); if (!reply) return; + const auto raw = reply->rawResult(); + +#if QT_VERSION >= QT_VERSION_CHECK(6, 4, 0) + if(raw.functionCode() == QModbusRequest::MaskWriteRegister && + reply->error() == QModbusDevice::InvalidResponseError) + { + reply->blockSignals(true); + reply->setError(QModbusDevice::NoError, QString()); + reply->blockSignals(false); + } +#endif + emit modbusReply(reply); - const auto raw = reply->rawResult(); auto onError = [this, reply, raw](const QString& errorDesc, int requestId) { if (reply->error() == QModbusDevice::ProtocolError) @@ -629,10 +640,6 @@ void ModbusClient::on_writeReply() break; case QModbusRequest::MaskWriteRegister: - #if QT_VERSION >= QT_VERSION_CHECK(6, 4, 0) - if(reply->error() == QModbusDevice::InvalidResponseError) - break; - #endif onError(tr("Mask Register Write Failure"), requestId); break; From 0a44785a0270d4188d9d260dd92fa557017de5b5 Mon Sep 17 00:00:00 2001 From: sanny32 Date: Mon, 2 Oct 2023 16:12:22 +0300 Subject: [PATCH 24/90] Correct write user message --- omodscan/controls/bytelistlineedit.cpp | 12 ++++++------ omodscan/dialogs/dialogusermsg.cpp | 5 ++++- omodscan/dialogs/dialogusermsg.h | 2 +- omodscan/dialogs/dialogusermsg.ui | 5 ++++- omodscan/mainwindow.cpp | 26 +++++++++++++++++++++++++- omodscan/modbusclient.cpp | 1 + 6 files changed, 41 insertions(+), 10 deletions(-) diff --git a/omodscan/controls/bytelistlineedit.cpp b/omodscan/controls/bytelistlineedit.cpp index 5e64a79..9b0fef8 100644 --- a/omodscan/controls/bytelistlineedit.cpp +++ b/omodscan/controls/bytelistlineedit.cpp @@ -50,7 +50,7 @@ void ByteListLineEdit::setValue(const QByteArray& value) QStringList text; for(auto&& v : value) text.push_back(QString::number((quint8)v)); - QLineEdit::setText(text.join(',')); + QLineEdit::setText(text.join(", ")); QLineEdit::setCursorPosition(0); } break; @@ -60,7 +60,7 @@ void ByteListLineEdit::setValue(const QByteArray& value) QStringList text; for(auto&& v : value) text.push_back(QString("%1").arg((quint8)v, 2, 16, QLatin1Char('0'))); - QLineEdit::setText(text.join(',').toUpper()); + QLineEdit::setText(text.join(", ").toUpper()); QLineEdit::setCursorPosition(0); } break; @@ -146,7 +146,7 @@ void ByteListLineEdit::on_textChanged(const QString& text) for(auto&& s : text.split(',')) { bool ok; - const quint8 v = s.toUInt(&ok); + const quint8 v = s.trimmed().toUInt(&ok); if(ok) value.push_back(v); } } @@ -157,7 +157,7 @@ void ByteListLineEdit::on_textChanged(const QString& text) for(auto&& s : text.split(',')) { bool ok; - const quint8 v = s.toUInt(&ok, 16); + const quint8 v = s.trimmed().toUInt(&ok, 16); if(ok) value.push_back(v); } } @@ -184,7 +184,7 @@ void ByteListLineEdit::updateValue() for(auto&& s : text().split(',')) { bool ok; - const quint8 v = s.toUInt(&ok); + const quint8 v = s.trimmed().toUInt(&ok); if(ok) value.push_back(v); } @@ -198,7 +198,7 @@ void ByteListLineEdit::updateValue() for(auto&& s : text().split(',')) { bool ok; - const quint8 v = s.toUInt(&ok, 16); + const quint8 v = s.trimmed().toUInt(&ok, 16); if(ok) value.push_back(v); } diff --git a/omodscan/dialogs/dialogusermsg.cpp b/omodscan/dialogs/dialogusermsg.cpp index cd4379c..55d68a4 100644 --- a/omodscan/dialogs/dialogusermsg.cpp +++ b/omodscan/dialogs/dialogusermsg.cpp @@ -9,10 +9,12 @@ /// /// \brief DialogUserMsg::DialogUserMsg /// \param slaveAddress +/// \param func /// \param mode +/// \param client /// \param parent /// -DialogUserMsg::DialogUserMsg(quint8 slaveAddress, DataDisplayMode mode, ModbusClient& client, QWidget *parent) : +DialogUserMsg::DialogUserMsg(quint8 slaveAddress, QModbusPdu::FunctionCode func, DataDisplayMode mode, ModbusClient& client, QWidget *parent) : QFixedSizeDialog(parent) , ui(new Ui::DialogUserMsg) ,_modbusClient(client) @@ -22,6 +24,7 @@ DialogUserMsg::DialogUserMsg(quint8 slaveAddress, DataDisplayMode mode, ModbusCl ui->lineEditSlaveAddress->setInputRange(ModbusLimits::slaveRange()); ui->lineEditSlaveAddress->setValue(slaveAddress); ui->lineEditFunction->setInputRange(0, 255); + ui->lineEditFunction->setValue(func); switch(mode) { diff --git a/omodscan/dialogs/dialogusermsg.h b/omodscan/dialogs/dialogusermsg.h index 26a17ee..8bc355d 100644 --- a/omodscan/dialogs/dialogusermsg.h +++ b/omodscan/dialogs/dialogusermsg.h @@ -15,7 +15,7 @@ class DialogUserMsg : public QFixedSizeDialog Q_OBJECT public: - explicit DialogUserMsg(quint8 slaveAddres, DataDisplayMode mode, ModbusClient& client, QWidget *parent = nullptr); + explicit DialogUserMsg(quint8 slaveAddres, QModbusPdu::FunctionCode func, DataDisplayMode mode, ModbusClient& client, QWidget *parent = nullptr); ~DialogUserMsg(); void accept() override; diff --git a/omodscan/dialogs/dialogusermsg.ui b/omodscan/dialogs/dialogusermsg.ui index 9ed16ca..bacd64f 100644 --- a/omodscan/dialogs/dialogusermsg.ui +++ b/omodscan/dialogs/dialogusermsg.ui @@ -7,7 +7,7 @@ 0 0 442 - 200 + 226 @@ -18,6 +18,9 @@ + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + diff --git a/omodscan/mainwindow.cpp b/omodscan/mainwindow.cpp index 895f9a0..99680b9 100644 --- a/omodscan/mainwindow.cpp +++ b/omodscan/mainwindow.cpp @@ -713,7 +713,31 @@ void MainWindow::on_actionUserMsg_triggered() const auto dd = frm->displayDefinition(); const auto mode = frm->dataDisplayMode(); - DialogUserMsg dlg(dd.DeviceId, mode, _modbusClient, this); + QModbusPdu::FunctionCode func; + switch(dd.PointType) + { + case QModbusDataUnit::Coils: + func = QModbusPdu::ReadCoils; + break; + + case QModbusDataUnit::DiscreteInputs: + func = QModbusPdu::ReadDiscreteInputs; + break; + + case QModbusDataUnit::HoldingRegisters: + func = QModbusPdu::ReadHoldingRegisters; + break; + + case QModbusDataUnit::InputRegisters: + func = QModbusPdu::ReadInputRegisters; + break; + + default: + func = QModbusPdu::Invalid; + break; + } + + DialogUserMsg dlg(dd.DeviceId, func, mode, _modbusClient, this); dlg.exec(); } diff --git a/omodscan/modbusclient.cpp b/omodscan/modbusclient.cpp index a0d0ec1..35f4376 100644 --- a/omodscan/modbusclient.cpp +++ b/omodscan/modbusclient.cpp @@ -129,6 +129,7 @@ void ModbusClient::sendRawRequest(const QModbusRequest& request, int server, int return; } + emit modbusRequest(requestId, server, request); if(auto reply = _modbusClient->sendRawRequest(request, server)) { reply->setProperty("RequestId", requestId); From 67e24053b680fb684bf9d1a8e63b54b66b47ddc6 Mon Sep 17 00:00:00 2001 From: sanny32 Date: Mon, 2 Oct 2023 16:51:04 +0300 Subject: [PATCH 25/90] Split by space in ByteListLineEdit control --- omodscan/controls/bytelistlineedit.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/omodscan/controls/bytelistlineedit.cpp b/omodscan/controls/bytelistlineedit.cpp index 9b0fef8..cd554af 100644 --- a/omodscan/controls/bytelistlineedit.cpp +++ b/omodscan/controls/bytelistlineedit.cpp @@ -50,7 +50,7 @@ void ByteListLineEdit::setValue(const QByteArray& value) QStringList text; for(auto&& v : value) text.push_back(QString::number((quint8)v)); - QLineEdit::setText(text.join(", ")); + QLineEdit::setText(text.join(' ')); QLineEdit::setCursorPosition(0); } break; @@ -60,7 +60,7 @@ void ByteListLineEdit::setValue(const QByteArray& value) QStringList text; for(auto&& v : value) text.push_back(QString("%1").arg((quint8)v, 2, 16, QLatin1Char('0'))); - QLineEdit::setText(text.join(", ").toUpper()); + QLineEdit::setText(text.join(' ').toUpper()); QLineEdit::setCursorPosition(0); } break; @@ -94,11 +94,11 @@ void ByteListLineEdit::setInputMode(InputMode mode) switch(mode) { case DecMode: - setValidator(new QRegularExpressionValidator(QRegularExpression("(?:[0-9]{1,2}[,]{0,1})*"), this)); + setValidator(new QRegularExpressionValidator(QRegularExpression("(?:[0-9]{1,2}[\\s]{0,1})*"), this)); break; case HexMode: - setValidator(new QRegularExpressionValidator(QRegularExpression("(?:[0-9a-fA-F]{1,2}[,]{0,1})*"), this)); + setValidator(new QRegularExpressionValidator(QRegularExpression("(?:[0-9a-fA-F]{1,2}[\\s]{0,1})*"), this)); break; } setValue(_value); @@ -143,7 +143,7 @@ void ByteListLineEdit::on_textChanged(const QString& text) { case DecMode: { - for(auto&& s : text.split(',')) + for(auto&& s : text.split(' ')) { bool ok; const quint8 v = s.trimmed().toUInt(&ok); @@ -154,7 +154,7 @@ void ByteListLineEdit::on_textChanged(const QString& text) case HexMode: { - for(auto&& s : text.split(',')) + for(auto&& s : text.split(' ')) { bool ok; const quint8 v = s.trimmed().toUInt(&ok, 16); @@ -181,7 +181,7 @@ void ByteListLineEdit::updateValue() { case DecMode: { - for(auto&& s : text().split(',')) + for(auto&& s : text().split(' ')) { bool ok; const quint8 v = s.trimmed().toUInt(&ok); @@ -195,7 +195,7 @@ void ByteListLineEdit::updateValue() case HexMode: { - for(auto&& s : text().split(',')) + for(auto&& s : text().split(' ')) { bool ok; const quint8 v = s.trimmed().toUInt(&ok, 16); From c617deb6355e0ecf87a36baf734c696f217ce73a Mon Sep 17 00:00:00 2001 From: sanny32 Date: Mon, 2 Oct 2023 16:51:23 +0300 Subject: [PATCH 26/90] Correct creation of modbus message object --- omodscan/modbusmessages/modbusmessage.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/omodscan/modbusmessages/modbusmessage.cpp b/omodscan/modbusmessages/modbusmessage.cpp index 6fbc5d0..5e87957 100644 --- a/omodscan/modbusmessages/modbusmessage.cpp +++ b/omodscan/modbusmessages/modbusmessage.cpp @@ -85,6 +85,6 @@ const ModbusMessage* ModbusMessage::create(const QModbusPdu& pdu, const QDateTim else return new ReadFifoQueueResponse(pdu, timestamp, deviceId); default: - return nullptr; + return new ModbusMessage(pdu, timestamp, deviceId, request); } } From 735a832fc0888ac4fa4aa881725417ce6ef89434 Mon Sep 17 00:00:00 2001 From: ananev-aa Date: Mon, 2 Oct 2023 20:14:47 +0300 Subject: [PATCH 27/90] Correct modbus scanner button 'Start Scan' accessibility --- omodscan/dialogs/dialogmodbusscanner.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/omodscan/dialogs/dialogmodbusscanner.cpp b/omodscan/dialogs/dialogmodbusscanner.cpp index 8bfae46..a01fc90 100644 --- a/omodscan/dialogs/dialogmodbusscanner.cpp +++ b/omodscan/dialogs/dialogmodbusscanner.cpp @@ -135,7 +135,7 @@ void DialogModbusScanner::on_awake() ui->groupBoxSubnetMask->setEnabled(!inProgress); ui->groupBoxRequest->setEnabled(!inProgress); ui->pushButtonClear->setEnabled(!inProgress); - ui->pushButtonScan->setEnabled(ui->comboBoxSerial->count() > 0); + ui->pushButtonScan->setEnabled((rtuScanning && ui->comboBoxSerial->count() > 0) || !rtuScanning); ui->pushButtonScan->setText(inProgress ? tr("Stop Scan") : tr("Start Scan")); } From f2d43b3e2caf1abef8c6d7091f0eb2127656571a Mon Sep 17 00:00:00 2001 From: sanny32 Date: Tue, 3 Oct 2023 15:55:29 +0300 Subject: [PATCH 28/90] Developing new log view --- omodscan/controls/bytelistlineedit.cpp | 11 +- omodscan/controls/modbusmessagewidget.cpp | 269 +++++++++++++----- omodscan/controls/modbusmessagewidget.h | 4 + omodscan/dialogs/dialogusermsg.cpp | 23 +- omodscan/dialogs/dialogusermsg.h | 4 +- omodscan/dialogs/dialogusermsg.ui | 37 ++- omodscan/formmodsca.cpp | 73 +++-- omodscan/formmodsca.h | 2 +- omodscan/mainwindow.cpp | 5 +- omodscan/modbusfunction.h | 5 + omodscan/modbusmessages/diagnostics.h | 17 ++ omodscan/modbusmessages/getcommeventcounter.h | 8 + omodscan/modbusmessages/getcommeventlog.h | 8 + omodscan/modbusmessages/maskwriteregister.h | 16 ++ omodscan/modbusmessages/modbusmessage.h | 21 +- omodscan/modbusmessages/readcoils.h | 16 ++ omodscan/modbusmessages/readdiscreteinputs.h | 16 ++ omodscan/modbusmessages/readexceptionstatus.h | 8 + omodscan/modbusmessages/readfifoqueue.h | 16 ++ omodscan/modbusmessages/readfilerecord.h | 16 ++ .../modbusmessages/readholdingregisters.h | 16 ++ omodscan/modbusmessages/readinputregisters.h | 16 ++ .../readwritemultipleregisters.h | 16 ++ omodscan/modbusmessages/reportserverid.h | 8 + omodscan/modbusmessages/writefilerecord.h | 16 ++ omodscan/modbusmessages/writemultiplecoils.h | 16 ++ .../modbusmessages/writemultipleregisters.h | 16 ++ omodscan/modbusmessages/writesinglecoil.h | 16 ++ omodscan/modbusmessages/writesingleregister.h | 16 ++ 29 files changed, 563 insertions(+), 148 deletions(-) diff --git a/omodscan/controls/bytelistlineedit.cpp b/omodscan/controls/bytelistlineedit.cpp index cd554af..9a3ccd5 100644 --- a/omodscan/controls/bytelistlineedit.cpp +++ b/omodscan/controls/bytelistlineedit.cpp @@ -1,4 +1,5 @@ #include +#include "formatutils.h" #include "bytelistlineedit.h" /// @@ -47,20 +48,14 @@ void ByteListLineEdit::setValue(const QByteArray& value) { case DecMode: { - QStringList text; - for(auto&& v : value) - text.push_back(QString::number((quint8)v)); - QLineEdit::setText(text.join(' ')); + QLineEdit::setText(formatByteArray(DataDisplayMode::Decimal, value)); QLineEdit::setCursorPosition(0); } break; case HexMode: { - QStringList text; - for(auto&& v : value) - text.push_back(QString("%1").arg((quint8)v, 2, 16, QLatin1Char('0'))); - QLineEdit::setText(text.join(' ').toUpper()); + QLineEdit::setText(formatByteArray(DataDisplayMode::Hex, value)); QLineEdit::setCursorPosition(0); } break; diff --git a/omodscan/controls/modbusmessagewidget.cpp b/omodscan/controls/modbusmessagewidget.cpp index c1a87a0..9748327 100644 --- a/omodscan/controls/modbusmessagewidget.cpp +++ b/omodscan/controls/modbusmessagewidget.cpp @@ -9,9 +9,11 @@ /// ModbusMessageWidget::ModbusMessageWidget(QWidget *parent) : QListWidget(parent) + ,_showTimestamp(true) ,_msg(nullptr) { setItemDelegate(new HtmlDelegate(this)); + setEditTriggers(QAbstractItemView::NoEditTriggers); } /// @@ -42,6 +44,25 @@ void ModbusMessageWidget::setDataDisplayMode(DataDisplayMode mode) update(); } +/// +/// \brief ModbusMessageWidget::showTimestamp +/// \return +/// +bool ModbusMessageWidget::showTimestamp() const +{ + return _showTimestamp; +} + +/// +/// \brief ModbusMessageWidget::setShowTimestamp +/// \param on +/// +void ModbusMessageWidget::setShowTimestamp(bool on) +{ + _showTimestamp = on; + update(); +} + /// /// \brief ModbusMessageWidget::modbusMessage /// \return @@ -67,13 +88,20 @@ void ModbusMessageWidget::setModbusMessage(const ModbusMessage* msg) void ModbusMessageWidget::update() { QListWidget::clear(); + if(_msg == nullptr) return; - const auto function = QString("%1 (%2)").arg(formatByteValue(_dataDisplayMode, _msg->function()), _msg->function()); + if(!_msg->isValid()) + { + if(_msg->isRequest()) + addItem(tr("*** INVALID MODBUS REQUEST ***")); + else if(!_msg->isException()) + addItem(tr("*** INVALID MODBUS RESPONSE ***")); + } addItem(tr("Type: %1").arg(_msg->isRequest() ? tr("Tx Message") : tr("Rx Message"))); - addItem(tr("Timestamp: %1").arg(_msg->timestamp().toString(Qt::ISODateWithMs))); + if(_showTimestamp) addItem(tr("Timestamp: %1").arg(_msg->timestamp().toString(Qt::ISODateWithMs))); addItem(tr("Device ID: %1").arg(formatByteValue(_dataDisplayMode, _msg->deviceId()))); if(_msg->isException()) @@ -84,6 +112,10 @@ void ModbusMessageWidget::update() return; } + const auto func = _msg->function(); + const auto function = func.isValid() ? + QString("%1 (%2)").arg(formatByteValue(_dataDisplayMode, func), func) : + formatByteValue(_dataDisplayMode, func); addItem(tr("Function Code: %1").arg(function)); switch(_msg->function()) @@ -92,14 +124,18 @@ void ModbusMessageWidget::update() if(_msg->isRequest()) { auto req = reinterpret_cast(_msg); - addItem(tr("Start Address: %1").arg(formatWordValue(_dataDisplayMode, req->startAddress()))); - addItem(tr("Length: %1").arg(formatWordValue(_dataDisplayMode, req->length()))); + const auto startAddress = req->isValid() ? formatWordValue(_dataDisplayMode, req->startAddress()) : "??"; + const auto length = req->isValid() ? formatWordValue(_dataDisplayMode, req->length()): "??"; + addItem(tr("Start Address: %1").arg(startAddress)); + addItem(tr("Length: %1").arg(length)); } else { auto resp = reinterpret_cast(_msg); - addItem(tr("Byte Count: %1").arg(formatByteValue(_dataDisplayMode, resp->byteCount()))); - addItem(tr("Coil Status: %1").arg(formatByteArray(_dataDisplayMode, resp->coilStatus()))); + const auto byteCount = resp->isValid() ? formatByteValue(_dataDisplayMode, resp->byteCount()) : "?"; + const auto coilStatus = resp->isValid() ? formatByteArray(_dataDisplayMode, resp->coilStatus()) : "???"; + addItem(tr("Byte Count: %1").arg(byteCount)); + addItem(tr("Coil Status: %1").arg(coilStatus)); } break; @@ -107,14 +143,18 @@ void ModbusMessageWidget::update() if(_msg->isRequest()) { auto req = reinterpret_cast(_msg); - addItem(tr("Start Address: %1").arg(formatWordValue(_dataDisplayMode, req->startAddress()))); - addItem(tr("Length: %1").arg(formatWordValue(_dataDisplayMode, req->length()))); + const auto startAddress = req->isValid() ? formatWordValue(_dataDisplayMode, req->startAddress()) : "??"; + const auto length = req->isValid() ? formatWordValue(_dataDisplayMode, req->length()): "??"; + addItem(tr("Start Address: %1").arg(startAddress)); + addItem(tr("Length: %1").arg(length)); } else { auto resp = reinterpret_cast(_msg); - addItem(tr("Byte Count: %1").arg(formatByteValue(_dataDisplayMode, resp->byteCount()))); - addItem(tr("Input Status: %1").arg(formatByteArray(_dataDisplayMode, resp->inputStatus()))); + const auto byteCount = resp->isValid() ? formatByteValue(_dataDisplayMode, resp->byteCount()) : "?"; + const auto inputStatus = resp->isValid() ? formatByteArray(_dataDisplayMode, resp->inputStatus()) : "???"; + addItem(tr("Byte Count: %1").arg(byteCount)); + addItem(tr("Input Status: %1").arg(inputStatus)); } break; @@ -122,14 +162,18 @@ void ModbusMessageWidget::update() if(_msg->isRequest()) { auto req = reinterpret_cast(_msg); - addItem(tr("Start Address: %1").arg(formatWordValue(_dataDisplayMode, req->startAddress()))); - addItem(tr("Length: %1").arg(formatWordValue(_dataDisplayMode, req->length()))); + const auto startAddress = req->isValid() ? formatWordValue(_dataDisplayMode, req->startAddress()) : "??"; + const auto length = req->isValid() ? formatWordValue(_dataDisplayMode, req->length()): "??"; + addItem(tr("Start Address: %1").arg(startAddress)); + addItem(tr("Length: %1").arg(length)); } else { auto resp = reinterpret_cast(_msg); - addItem(tr("Byte Count: %1").arg(formatByteValue(_dataDisplayMode, resp->byteCount()))); - addItem(tr("Register Value: %1").arg(formatByteArray(_dataDisplayMode, resp->registerValue()))); + const auto byteCount = resp->isValid() ? formatByteValue(_dataDisplayMode, resp->byteCount()) : "?"; + const auto registerValue = resp->isValid() ? formatByteArray(_dataDisplayMode, resp->registerValue()) : "???"; + addItem(tr("Byte Count: %1").arg(byteCount)); + addItem(tr("Register Value: %1").arg(registerValue)); } break; @@ -137,14 +181,18 @@ void ModbusMessageWidget::update() if(_msg->isRequest()) { auto req = reinterpret_cast(_msg); - addItem(tr("Start Address: %1").arg(formatWordValue(_dataDisplayMode, req->startAddress()))); - addItem(tr("Length: %1").arg(formatWordValue(_dataDisplayMode, req->length()))); + const auto startAddress = req->isValid() ? formatWordValue(_dataDisplayMode, req->startAddress()) : "??"; + const auto length = req->isValid() ? formatWordValue(_dataDisplayMode, req->length()): "??"; + addItem(tr("Start Address: %1").arg(startAddress)); + addItem(tr("Length: %1").arg(length)); } else { auto resp = reinterpret_cast(_msg); - addItem(tr("Byte Count: %1").arg(formatByteValue(_dataDisplayMode, resp->byteCount()))); - addItem(tr("Input Registers: %1").arg(formatByteArray(_dataDisplayMode, resp->registerValue()))); + const auto byteCount = resp->isValid() ? formatByteValue(_dataDisplayMode, resp->byteCount()) : "?"; + const auto registerValue = resp->isValid() ? formatByteArray(_dataDisplayMode, resp->registerValue()) : "???"; + addItem(tr("Byte Count: %1").arg(byteCount)); + addItem(tr("Input Registers: %1").arg(registerValue)); } break; @@ -152,14 +200,18 @@ void ModbusMessageWidget::update() if(_msg->isRequest()) { auto req = reinterpret_cast(_msg); - addItem(tr("Output Address: %1").arg(formatWordValue(_dataDisplayMode, req->address()))); - addItem(tr("Output Value: %1").arg(formatWordValue(_dataDisplayMode, req->value()))); + const auto outputAddress = req->isValid() ? formatWordValue(_dataDisplayMode, req->address()) : "??"; + const auto outputValue = req->isValid() ? formatWordValue(_dataDisplayMode, req->value()) : "??"; + addItem(tr("Output Address: %1").arg(outputAddress)); + addItem(tr("Output Value: %1").arg(outputValue)); } else { auto resp = reinterpret_cast(_msg); - addItem(tr("Output Address: %1").arg(formatWordValue(_dataDisplayMode, resp->address()))); - addItem(tr("Output Value: %1").arg(formatWordValue(_dataDisplayMode, resp->value()))); + const auto outputAddress = resp->isValid() ? formatWordValue(_dataDisplayMode, resp->address()) : "??"; + const auto outputValue = resp->isValid() ? formatWordValue(_dataDisplayMode, resp->value()) : "??"; + addItem(tr("Output Address: %1").arg(outputAddress)); + addItem(tr("Output Value: %1").arg(outputValue)); } break; @@ -167,14 +219,18 @@ void ModbusMessageWidget::update() if(_msg->isRequest()) { auto req = reinterpret_cast(_msg); - addItem(tr("Register Address: %1").arg(formatWordValue(_dataDisplayMode, req->address()))); - addItem(tr("Register Value: %1").arg(formatWordValue(_dataDisplayMode, req->value()))); + const auto registerAddress = req->isValid() ? formatWordValue(_dataDisplayMode, req->address()) : "??"; + const auto registerValue = req->isValid() ? formatWordValue(_dataDisplayMode, req->value()) : "??"; + addItem(tr("Register Address: %1").arg(registerAddress)); + addItem(tr("Register Value: %1").arg(registerValue)); } else { auto resp = reinterpret_cast(_msg); - addItem(tr("Register Address: %1").arg(formatWordValue(_dataDisplayMode, resp->address()))); - addItem(tr("Register Value: %1").arg(formatWordValue(_dataDisplayMode, resp->value()))); + const auto registerAddress = resp->isValid() ? formatWordValue(_dataDisplayMode, resp->address()) : "??"; + const auto registerValue = resp->isValid() ? formatWordValue(_dataDisplayMode, resp->value()) : "??"; + addItem(tr("Register Address: %1").arg(registerAddress)); + addItem(tr("Register Value: %1").arg(registerValue)); } break; @@ -182,7 +238,8 @@ void ModbusMessageWidget::update() if(!_msg->isRequest()) { auto resp = reinterpret_cast(_msg); - addItem(tr("Output Data: %1").arg(formatByteValue(_dataDisplayMode, resp->outputData()))); + const auto outputData = resp->isValid() ? formatByteValue(_dataDisplayMode, resp->outputData()) : "?"; + addItem(tr("Output Data: %1").arg(outputData)); } break; @@ -190,14 +247,18 @@ void ModbusMessageWidget::update() if(_msg->isRequest()) { auto req = reinterpret_cast(_msg); - addItem(tr("Sub-function: %1").arg(formatWordValue(_dataDisplayMode, req->subfunc()))); - addItem(tr("Data: %1").arg(formatByteArray(_dataDisplayMode, req->data()))); + const auto subFunc = req->isValid() ? formatWordValue(_dataDisplayMode, req->subfunc()) : "??"; + const auto data = req->isValid() ? formatByteArray(_dataDisplayMode, req->data()) : "???"; + addItem(tr("Sub-function: %1").arg(subFunc)); + addItem(tr("Data: %1").arg(data)); } else { auto resp = reinterpret_cast(_msg); - addItem(tr("Sub-function: %1").arg(formatWordValue(_dataDisplayMode, resp->subfunc()))); - addItem(tr("Data: %1").arg(formatByteArray(_dataDisplayMode, resp->data()))); + const auto subFunc = resp->isValid() ? formatWordValue(_dataDisplayMode, resp->subfunc()) : "??"; + const auto data = resp->isValid() ? formatByteArray(_dataDisplayMode, resp->data()) : "???"; + addItem(tr("Sub-function: %1").arg(subFunc)); + addItem(tr("Data: %1").arg(data)); } break; @@ -205,8 +266,10 @@ void ModbusMessageWidget::update() if(!_msg->isRequest()) { auto resp = reinterpret_cast(_msg); - addItem(tr("Status: %1").arg(formatWordValue(_dataDisplayMode, resp->status()))); - addItem(tr("Event Count: %1").arg(formatWordValue(_dataDisplayMode, resp->eventCount()))); + const auto status = resp->isValid() ? formatWordValue(_dataDisplayMode, resp->status()) : "??"; + const auto eventCount = resp->isValid() ? formatWordValue(_dataDisplayMode, resp->eventCount()) : "??"; + addItem(tr("Status: %1").arg(status)); + addItem(tr("Event Count: %1").arg(eventCount)); } break; @@ -214,11 +277,16 @@ void ModbusMessageWidget::update() if(!_msg->isRequest()) { auto resp = reinterpret_cast(_msg); - addItem(tr("Byte Count: %1").arg(formatByteValue(_dataDisplayMode, resp->byteCount()))); - addItem(tr("Status: %1").arg(formatWordValue(_dataDisplayMode, resp->status()))); - addItem(tr("Event Count: %1").arg(formatWordValue(_dataDisplayMode, resp->eventCount()))); - addItem(tr("Message Count: %1").arg(formatWordValue(_dataDisplayMode, resp->messageCount()))); - addItem(tr("Events: %1").arg(formatByteArray(_dataDisplayMode, resp->events()))); + const auto byteCount = resp->isValid() ? formatByteValue(_dataDisplayMode, resp->byteCount()) : "?"; + const auto status = resp->isValid() ? formatWordValue(_dataDisplayMode, resp->status()) : "??"; + const auto eventCount = resp->isValid() ? formatWordValue(_dataDisplayMode, resp->eventCount()) : "??"; + const auto messageCount = resp->isValid() ? formatWordValue(_dataDisplayMode, resp->messageCount()) : "??"; + const auto events = resp->isValid() ? formatByteArray(_dataDisplayMode, resp->events()) : "???"; + addItem(tr("Byte Count: %1").arg(byteCount)); + addItem(tr("Status: %1").arg(status)); + addItem(tr("Event Count: %1").arg(eventCount)); + addItem(tr("Message Count: %1").arg(messageCount)); + addItem(tr("Events: %1").arg(events)); } break; @@ -226,16 +294,22 @@ void ModbusMessageWidget::update() if(_msg->isRequest()) { auto req = reinterpret_cast(_msg); - addItem(tr("Starting Address: %1").arg(formatWordValue(_dataDisplayMode, req->startAddress()))); - addItem(tr("Quantity of Outputs: %1").arg(formatWordValue(_dataDisplayMode, req->quantity()))); - addItem(tr("Byte Count: %1").arg(formatByteValue(_dataDisplayMode, req->byteCount()))); - addItem(tr("Output Value: %1").arg(formatByteArray(_dataDisplayMode, req->values()))); + const auto startAddr = req->isValid() ? formatWordValue(_dataDisplayMode, req->startAddress()) : "??"; + const auto quantity = req->isValid() ? formatWordValue(_dataDisplayMode, req->quantity()) : "??"; + const auto byteCount = req->isValid() ? formatByteValue(_dataDisplayMode, req->byteCount()) : "?"; + const auto values = req->isValid() ? formatByteArray(_dataDisplayMode, req->values()) : "???"; + addItem(tr("Starting Address: %1").arg(startAddr)); + addItem(tr("Quantity of Outputs: %1").arg(quantity)); + addItem(tr("Byte Count: %1").arg(byteCount)); + addItem(tr("Output Value: %1").arg(values)); } else { auto resp = reinterpret_cast(_msg); - addItem(tr("Starting Address: %1").arg(formatWordValue(_dataDisplayMode, resp->startAddress()))); - addItem(tr("Quantity of Outputs: %1").arg(formatWordValue(_dataDisplayMode, resp->quantity()))); + const auto startAddr = resp->isValid() ? formatWordValue(_dataDisplayMode, resp->startAddress()) : "??"; + const auto quantity = resp->isValid() ? formatWordValue(_dataDisplayMode, resp->quantity()) : "??"; + addItem(tr("Starting Address: %1").arg(startAddr)); + addItem(tr("Quantity of Outputs: %1").arg(quantity)); } break; @@ -243,16 +317,22 @@ void ModbusMessageWidget::update() if(_msg->isRequest()) { auto req = reinterpret_cast(_msg); - addItem(tr("Starting Address: %1").arg(formatWordValue(_dataDisplayMode, req->startAddress()))); - addItem(tr("Quantity of Registers: %1").arg(formatWordValue(_dataDisplayMode, req->quantity()))); - addItem(tr("Byte Count: %1").arg(formatByteValue(_dataDisplayMode, req->byteCount()))); - addItem(tr("Registers Value: %1").arg(formatByteArray(_dataDisplayMode, req->values()))); + const auto startAddr = req->isValid() ? formatWordValue(_dataDisplayMode, req->startAddress()) : "??"; + const auto quantity = req->isValid() ? formatWordValue(_dataDisplayMode, req->quantity()) : "??"; + const auto byteCount = req->isValid() ? formatByteValue(_dataDisplayMode, req->byteCount()) : "?"; + const auto values = req->isValid() ? formatByteArray(_dataDisplayMode, req->values()) : "???"; + addItem(tr("Starting Address: %1").arg(startAddr)); + addItem(tr("Quantity of Registers: %1").arg(quantity)); + addItem(tr("Byte Count: %1").arg(byteCount)); + addItem(tr("Registers Value: %1").arg(values)); } else { auto resp = reinterpret_cast(_msg); - addItem(tr("Starting Address: %1").arg(formatWordValue(_dataDisplayMode, resp->startAddress()))); - addItem(tr("Quantity of Registers: %1").arg(formatWordValue(_dataDisplayMode, resp->quantity()))); + const auto startAddr = resp->isValid() ? formatWordValue(_dataDisplayMode, resp->startAddress()) : "??"; + const auto quantity = resp->isValid() ? formatWordValue(_dataDisplayMode, resp->quantity()) : "??"; + addItem(tr("Starting Address: %1").arg(startAddr)); + addItem(tr("Quantity of Registers: %1").arg(quantity)); } break; @@ -260,8 +340,10 @@ void ModbusMessageWidget::update() if(!_msg->isRequest()) { auto resp = reinterpret_cast(_msg); - addItem(tr("Byte Count: %1").arg(formatByteValue(_dataDisplayMode, resp->byteCount()))); - addItem(tr("Data: %1").arg(formatByteArray(_dataDisplayMode, resp->data()))); + const auto byteCount = resp->isValid() ? formatByteValue(_dataDisplayMode, resp->byteCount()) : "?"; + const auto data = resp->isValid() ? formatByteArray(_dataDisplayMode, resp->data()) : "?"; + addItem(tr("Byte Count: %1").arg(byteCount)); + addItem(tr("Data: %1").arg(data)); } break; @@ -269,14 +351,18 @@ void ModbusMessageWidget::update() if(_msg->isRequest()) { auto req = reinterpret_cast(_msg); - addItem(tr("Byte Count: %1").arg(formatByteValue(_dataDisplayMode, req->byteCount()))); - addItem(tr("Data: %1").arg(formatByteArray(_dataDisplayMode, req->data()))); + const auto byteCount = req->isValid() ? formatByteValue(_dataDisplayMode, req->byteCount()) : "?"; + const auto data = req->isValid() ? formatByteArray(_dataDisplayMode, req->data()) : "?"; + addItem(tr("Byte Count: %1").arg(byteCount)); + addItem(tr("Data: %1").arg(data)); } else { auto resp = reinterpret_cast(_msg); - addItem(tr("Byte Count: %1").arg(formatByteValue(_dataDisplayMode, resp->byteCount()))); - addItem(tr("Data: %1").arg(formatByteArray(_dataDisplayMode, resp->data()))); + const auto byteCount = resp->isValid() ? formatByteValue(_dataDisplayMode, resp->byteCount()) : "?"; + const auto data = resp->isValid() ? formatByteArray(_dataDisplayMode, resp->data()) : "?"; + addItem(tr("Byte Count: %1").arg(byteCount)); + addItem(tr("Data: %1").arg(data)); } break; @@ -284,14 +370,18 @@ void ModbusMessageWidget::update() if(_msg->isRequest()) { auto req = reinterpret_cast(_msg); - addItem(tr("Request _msg Length: %1").arg(formatByteValue(_dataDisplayMode, req->length()))); - addItem(tr("Data: %1").arg(formatByteArray(_dataDisplayMode, req->data()))); + const auto length = req->isValid() ? formatByteValue(_dataDisplayMode, req->length()) : "?"; + const auto data = req->isValid() ? formatByteArray(_dataDisplayMode, req->data()) : "???"; + addItem(tr("Request Data Length: %1").arg(length)); + addItem(tr("Data: %1").arg(data)); } else { auto resp = reinterpret_cast(_msg); - addItem(tr("Request _msg Length: %1").arg(formatByteValue(_dataDisplayMode, resp->length()))); - addItem(tr("Data: %1").arg(formatByteArray(_dataDisplayMode, resp->data()))); + const auto length = resp->isValid() ? formatByteValue(_dataDisplayMode, resp->length()) : "?"; + const auto data = resp->isValid() ? formatByteArray(_dataDisplayMode, resp->data()) : "???"; + addItem(tr("Response Data Length: %1").arg(length)); + addItem(tr("Data: %1").arg(data)); } break; @@ -299,16 +389,22 @@ void ModbusMessageWidget::update() if(_msg->isRequest()) { auto req = reinterpret_cast(_msg); - addItem(tr("Address: %1").arg(formatWordValue(_dataDisplayMode, req->address()))); - addItem(tr("And Mask: %1").arg(formatWordValue(_dataDisplayMode, req->andMask()))); - addItem(tr("Or Mask: %1").arg(formatWordValue(_dataDisplayMode, req->orMask()))); + const auto address = req->isValid() ? formatWordValue(_dataDisplayMode, req->address()) : "??"; + const auto andMask = req->isValid() ? formatWordValue(_dataDisplayMode, req->andMask()) : "??"; + const auto orMask = req->isValid() ? formatWordValue(_dataDisplayMode, req->orMask()) : "??"; + addItem(tr("Address: %1").arg(address)); + addItem(tr("And Mask: %1").arg(andMask)); + addItem(tr("Or Mask: %1").arg(orMask)); } else { auto resp = reinterpret_cast(_msg); - addItem(tr("Address: %1").arg(formatWordValue(_dataDisplayMode, resp->address()))); - addItem(tr("And Mask: %1").arg(formatWordValue(_dataDisplayMode, resp->andMask()))); - addItem(tr("Or Mask: %1").arg(formatWordValue(_dataDisplayMode, resp->orMask()))); + const auto address = resp->isValid() ? formatWordValue(_dataDisplayMode, resp->address()) : "??"; + const auto andMask = resp->isValid() ? formatWordValue(_dataDisplayMode, resp->andMask()) : "??"; + const auto orMask = resp->isValid() ? formatWordValue(_dataDisplayMode, resp->orMask()) : "??"; + addItem(tr("Address: %1").arg(address)); + addItem(tr("And Mask: %1").arg(andMask)); + addItem(tr("Or Mask: %1").arg(orMask)); } break; @@ -316,18 +412,26 @@ void ModbusMessageWidget::update() if(_msg->isRequest()) { auto req = reinterpret_cast(_msg); - addItem(tr("Read Starting Address: %1").arg(formatWordValue(_dataDisplayMode, req->readStartAddress()))); - addItem(tr("Quantity to Read: %1").arg(formatWordValue(_dataDisplayMode, req->readLength()))); - addItem(tr("Write Starting Address: %1").arg(formatWordValue(_dataDisplayMode, req->writeStartAddress()))); - addItem(tr("Quantity to Write: %1").arg(formatWordValue(_dataDisplayMode, req->writeLength()))); - addItem(tr("Write Byte Count: %1").arg(formatByteValue(_dataDisplayMode, req->writeByteCount()))); - addItem(tr("Write Registers Value: %1").arg(formatByteArray(_dataDisplayMode, req->writeValues()))); + const auto readStartAddr = req->isValid() ? formatWordValue(_dataDisplayMode, req->readStartAddress()) : "??"; + const auto readLength = req->isValid() ? formatWordValue(_dataDisplayMode, req->readLength()) : "??"; + const auto writeStartAddr = req->isValid() ? formatWordValue(_dataDisplayMode, req->writeStartAddress()) : "??"; + const auto writeLength = req->isValid() ? formatWordValue(_dataDisplayMode, req->writeLength()) : "??"; + const auto writeByteCount = req->isValid() ? formatByteValue(_dataDisplayMode, req->writeByteCount()) : "?"; + const auto writeValues = req->isValid() ? formatByteArray(_dataDisplayMode, req->writeValues()) : "???"; + addItem(tr("Read Starting Address: %1").arg(readStartAddr)); + addItem(tr("Quantity to Read: %1").arg(readLength)); + addItem(tr("Write Starting Address: %1").arg(writeStartAddr)); + addItem(tr("Quantity to Write: %1").arg(writeLength)); + addItem(tr("Write Byte Count: %1").arg(writeByteCount)); + addItem(tr("Write Registers Value: %1").arg(writeValues)); } else { auto resp = reinterpret_cast(_msg); - addItem(tr("Byte Count: %1").arg(formatByteValue(_dataDisplayMode, resp->byteCount()))); - addItem(tr("Registers Value: %1").arg(formatByteArray(_dataDisplayMode, resp->values()))); + const auto byteCount = resp->isValid() ? formatByteValue(_dataDisplayMode, resp->byteCount()): "?"; + const auto values = resp->isValid() ? formatByteArray(_dataDisplayMode, resp->values()) : "???"; + addItem(tr("Byte Count: %1").arg(byteCount)); + addItem(tr("Registers Value: %1").arg(values)); } break; @@ -335,19 +439,26 @@ void ModbusMessageWidget::update() if(_msg->isRequest()) { auto req = reinterpret_cast(_msg); - addItem(tr("FIFO Point Address: %1").arg(formatWordValue(_dataDisplayMode, req->fifoAddress()))); + const auto fifoAddr = req->isValid() ? formatWordValue(_dataDisplayMode, req->fifoAddress()) : "??"; + addItem(tr("FIFO Point Address: %1").arg(fifoAddr)); } else { auto resp = reinterpret_cast(_msg); - addItem(tr("Byte Count: %1").arg(formatByteValue(_dataDisplayMode, resp->byteCount()))); - addItem(tr("FIFO Count: %1").arg(formatByteValue(_dataDisplayMode, resp->fifoCount()))); - addItem(tr("FIFO Value Register: %1").arg(formatByteArray(_dataDisplayMode, resp->fifoValue()))); + const auto byteCount = resp->isValid() ? formatByteValue(_dataDisplayMode, resp->byteCount()) : "?"; + const auto fifoCount = resp->isValid() ? formatByteValue(_dataDisplayMode, resp->fifoCount()) : "?"; + const auto fifoValue = resp->isValid() ? formatByteArray(_dataDisplayMode, resp->fifoValue()) : "???"; + addItem(tr("Byte Count: %1").arg(byteCount)); + addItem(tr("FIFO Count: %1").arg(fifoCount)); + addItem(tr("FIFO Value Register: %1").arg(fifoValue)); } break; default: - addItem(tr("Data: %1").arg(formatByteArray(_dataDisplayMode, _msg->rawData()))); + { + const auto data = _msg->isValid() ? formatByteArray(_dataDisplayMode, _msg->rawData()) : "???"; + addItem(tr("Data: %1").arg(data)); + } break; } } diff --git a/omodscan/controls/modbusmessagewidget.h b/omodscan/controls/modbusmessagewidget.h index 691b49c..cba2060 100644 --- a/omodscan/controls/modbusmessagewidget.h +++ b/omodscan/controls/modbusmessagewidget.h @@ -21,11 +21,15 @@ class ModbusMessageWidget : public QListWidget const ModbusMessage* modbusMessage() const; void setModbusMessage(const ModbusMessage* msg); + bool showTimestamp() const; + void setShowTimestamp(bool on); + private: void update(); private: DataDisplayMode _dataDisplayMode; + bool _showTimestamp; const ModbusMessage* _msg; }; diff --git a/omodscan/dialogs/dialogusermsg.cpp b/omodscan/dialogs/dialogusermsg.cpp index 55d68a4..51c8ec5 100644 --- a/omodscan/dialogs/dialogusermsg.cpp +++ b/omodscan/dialogs/dialogusermsg.cpp @@ -2,6 +2,7 @@ #include #include #include +#include "modbusmessage.h" #include "modbuslimits.h" #include "dialogusermsg.h" #include "ui_dialogusermsg.h" @@ -15,7 +16,7 @@ /// \param parent /// DialogUserMsg::DialogUserMsg(quint8 slaveAddress, QModbusPdu::FunctionCode func, DataDisplayMode mode, ModbusClient& client, QWidget *parent) : - QFixedSizeDialog(parent) + QDialog(parent) , ui(new Ui::DialogUserMsg) ,_modbusClient(client) { @@ -25,6 +26,7 @@ DialogUserMsg::DialogUserMsg(quint8 slaveAddress, QModbusPdu::FunctionCode func, ui->lineEditSlaveAddress->setValue(slaveAddress); ui->lineEditFunction->setInputRange(0, 255); ui->lineEditFunction->setValue(func); + ui->responseInfo->setShowTimestamp(false); switch(mode) { @@ -83,19 +85,24 @@ void DialogUserMsg::on_modbusReply(QModbusReply* reply) { if(!reply) return; + if(reply->error() != QModbusDevice::NoError && + reply->error() != QModbusDevice::ProtocolError) + { + QMessageBox::warning(this, windowTitle(), reply->errorString()); + return; + } + if(0 != reply->property("RequestId").toInt()) { return; } - const auto raw = reply->rawResult(); + const auto response = reply->rawResult(); + const auto msg = ModbusMessage::create(response, QDateTime::currentDateTime(), reply->serverAddress(), false); - QByteArray data; - data.push_back(reply->serverAddress()); - data.push_back(raw.functionCode() | ( raw.isException() ? QModbusPdu::ExceptionByte : 0)); - data.push_back(raw.data()); + ui->lineEditResponse->setValue(*msg); + ui->responseInfo->setModbusMessage(msg); - ui->lineEditResponse->setValue(data); ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(true); } @@ -113,6 +120,7 @@ void DialogUserMsg::on_radioButtonHex_clicked(bool checked) ui->lineEditFunction->setInputMode(NumericLineEdit::HexMode); ui->lineEditSendData->setInputMode(ByteListLineEdit::HexMode); ui->lineEditResponse->setInputMode(ByteListLineEdit::HexMode); + ui->responseInfo->setDataDisplayMode(DataDisplayMode::Hex); } } @@ -130,5 +138,6 @@ void DialogUserMsg::on_radioButtonDecimal_clicked(bool checked) ui->lineEditFunction->setInputMode(NumericLineEdit::DecMode); ui->lineEditSendData->setInputMode(ByteListLineEdit::DecMode); ui->lineEditResponse->setInputMode(ByteListLineEdit::DecMode); + ui->responseInfo->setDataDisplayMode(DataDisplayMode::Decimal); } } diff --git a/omodscan/dialogs/dialogusermsg.h b/omodscan/dialogs/dialogusermsg.h index 8bc355d..3d60a56 100644 --- a/omodscan/dialogs/dialogusermsg.h +++ b/omodscan/dialogs/dialogusermsg.h @@ -2,7 +2,7 @@ #define DIALOGUSERMSG_H #include -#include "qfixedsizedialog.h" +#include #include "modbusclient.h" #include "enums.h" @@ -10,7 +10,7 @@ namespace Ui { class DialogUserMsg; } -class DialogUserMsg : public QFixedSizeDialog +class DialogUserMsg : public QDialog { Q_OBJECT diff --git a/omodscan/dialogs/dialogusermsg.ui b/omodscan/dialogs/dialogusermsg.ui index bacd64f..58e74fe 100644 --- a/omodscan/dialogs/dialogusermsg.ui +++ b/omodscan/dialogs/dialogusermsg.ui @@ -7,7 +7,7 @@ 0 0 442 - 226 + 332 @@ -120,7 +120,7 @@ Qt::Horizontal - QSizePolicy::Fixed + QSizePolicy::Expanding @@ -142,7 +142,14 @@ - + + + false + + + true + + @@ -151,14 +158,30 @@ Response Buffer - + + + false + true + + + + QAbstractItemView::NoEditTriggers + + + QAbstractItemView::NoSelection + + + true + + +
@@ -188,11 +211,15 @@ QLineEdit
bytelistlineedit.h
+ + ModbusMessageWidget + QListWidget +
modbusmessagewidget.h
+
lineEditFunction lineEditSendData - lineEditResponse radioButtonDecimal radioButtonHex lineEditSlaveAddress diff --git a/omodscan/formmodsca.cpp b/omodscan/formmodsca.cpp index 094a0cf..6b01860 100644 --- a/omodscan/formmodsca.cpp +++ b/omodscan/formmodsca.cpp @@ -513,7 +513,7 @@ void FormModSca::beginUpdate() /// \param reply /// \return /// -bool FormModSca::isValidReply(const QModbusReply* reply) +bool FormModSca::isValidReply(const QModbusReply* reply) const { const auto dd = displayDefinition(); const auto data = reply->result(); @@ -537,6 +537,33 @@ bool FormModSca::isValidReply(const QModbusReply* reply) return false; } +/// +/// \brief FormModSca::on_modbusRequest +/// \param requestId +/// \param deviceId +/// \param request +/// +void FormModSca::on_modbusRequest(int requestId, int deviceId, const QModbusRequest& request) +{ + if(requestId != _formId) + return; + + switch(request.functionCode()) + { + case QModbusPdu::ReadCoils: + case QModbusPdu::ReadDiscreteInputs: + case QModbusPdu::ReadHoldingRegisters: + case QModbusPdu::ReadInputRegisters: + ui->statisticWidget->increaseNumberOfPolls(); + break; + + default: + break; + } + + ui->outputWidget->updateTraffic(request, deviceId); +} + /// /// \brief FormModSca::on_modbusReply /// \param reply @@ -546,15 +573,13 @@ void FormModSca::on_modbusReply(QModbusReply* reply) if(!reply) return; const auto requestId = reply->property("RequestId").toInt(); - if((_formId != requestId && requestId != 0) || - reply->serverAddress() != ui->lineEditDeviceId->value()) - { + if(requestId != _formId) return; - } const auto data = reply->result(); const auto response = reply->rawResult(); const bool hasError = reply->error() != QModbusDevice::NoError; + const bool hasProtocolError = reply->error() == QModbusDevice::ProtocolError; switch(response.functionCode()) { @@ -562,11 +587,13 @@ void FormModSca::on_modbusReply(QModbusReply* reply) case QModbusRequest::ReadDiscreteInputs: case QModbusRequest::ReadInputRegisters: case QModbusRequest::ReadHoldingRegisters: - ui->outputWidget->updateTraffic(response, reply->serverAddress()); + if(!hasError || hasProtocolError) + ui->outputWidget->updateTraffic(response, reply->serverAddress()); break; default: - ui->outputWidget->updateTraffic(response, reply->serverAddress()); + if(!hasError || hasProtocolError) + ui->outputWidget->updateTraffic(response, reply->serverAddress()); if(!hasError) beginUpdate(); return; } @@ -584,7 +611,7 @@ void FormModSca::on_modbusReply(QModbusReply* reply) ui->statisticWidget->increaseValidSlaveResponses(); } } - else if (reply->error() == QModbusDevice::ProtocolError) + else if (hasProtocolError) { const auto ex = ModbusException(response.exceptionCode()); const auto errorString = QString("%1 (%2)").arg(ex, formatByteValue(DataDisplayMode::Hex, ex)); @@ -616,36 +643,6 @@ void FormModSca::on_modbusDisconnected(const ConnectionDetails&) ui->outputWidget->setStatus(tr("Device NOT CONNECTED!")); } -/// -/// \brief FormModSca::on_modbusRequest -/// \param requestId -/// \param deviceId -/// \param request -/// -void FormModSca::on_modbusRequest(int requestId, int deviceId, const QModbusRequest& request) -{ - if((requestId != _formId && requestId != 0) || - deviceId != ui->lineEditDeviceId->value()) - { - return; - } - - switch(request.functionCode()) - { - case QModbusPdu::ReadCoils: - case QModbusPdu::ReadDiscreteInputs: - case QModbusPdu::ReadHoldingRegisters: - case QModbusPdu::ReadInputRegisters: - ui->statisticWidget->increaseNumberOfPolls(); - break; - - default: - break; - } - - ui->outputWidget->updateTraffic(request, deviceId); -} - /// /// \brief FormModSca::on_lineEditAddress_valueChanged /// diff --git a/omodscan/formmodsca.h b/omodscan/formmodsca.h index a02919a..d271800 100644 --- a/omodscan/formmodsca.h +++ b/omodscan/formmodsca.h @@ -115,7 +115,7 @@ private slots: private: void beginUpdate(); - bool isValidReply(const QModbusReply* reply); + bool isValidReply(const QModbusReply* reply) const; private: Ui::FormModSca *ui; diff --git a/omodscan/mainwindow.cpp b/omodscan/mainwindow.cpp index 99680b9..4ca5b18 100644 --- a/omodscan/mainwindow.cpp +++ b/omodscan/mainwindow.cpp @@ -737,8 +737,9 @@ void MainWindow::on_actionUserMsg_triggered() break; } - DialogUserMsg dlg(dd.DeviceId, func, mode, _modbusClient, this); - dlg.exec(); + auto dlg = new DialogUserMsg(dd.DeviceId, func, mode, _modbusClient, this); + dlg->setAttribute(Qt::WA_DeleteOnClose, true); + dlg->show(); } /// diff --git a/omodscan/modbusfunction.h b/omodscan/modbusfunction.h index f98c0c9..7d58c76 100644 --- a/omodscan/modbusfunction.h +++ b/omodscan/modbusfunction.h @@ -14,6 +14,11 @@ class ModbusFunction { } + bool isValid() const + { + return _code >= 1 && _code <= 0x2B; + } + bool isException() const { return _code & QModbusPdu::ExceptionByte; diff --git a/omodscan/modbusmessages/diagnostics.h b/omodscan/modbusmessages/diagnostics.h index 1184e50..99351ef 100644 --- a/omodscan/modbusmessages/diagnostics.h +++ b/omodscan/modbusmessages/diagnostics.h @@ -21,6 +21,15 @@ class DiagnosticsRequest : public ModbusMessage Q_ASSERT((_funcCode & ~QModbusPdu::ExceptionByte) == QModbusPdu::Diagnostics); } + /// + /// \brief isValid + /// \return + /// + bool isValid() const override { + return ModbusMessage::isValid() && _data.size() > 2; + } + + /// /// \brief subfunc /// \return @@ -56,6 +65,14 @@ class DiagnosticsResponse : public ModbusMessage Q_ASSERT((_funcCode & ~QModbusPdu::ExceptionByte) == QModbusPdu::Diagnostics); } + /// + /// \brief isValid + /// \return + /// + bool isValid() const override { + return ModbusMessage::isValid() && _data.size() > 2; + } + /// /// \brief subfunc /// \return diff --git a/omodscan/modbusmessages/getcommeventcounter.h b/omodscan/modbusmessages/getcommeventcounter.h index 4b881c0..bc65f47 100644 --- a/omodscan/modbusmessages/getcommeventcounter.h +++ b/omodscan/modbusmessages/getcommeventcounter.h @@ -40,6 +40,14 @@ class GetCommEventCounterResponse : public ModbusMessage Q_ASSERT((_funcCode & ~QModbusPdu::ExceptionByte) == QModbusPdu::GetCommEventCounter); } + /// + /// \brief isValid + /// \return + /// + bool isValid() const override { + return ModbusMessage::isValid() && _data.size() == 4; + } + /// /// \brief status /// \return diff --git a/omodscan/modbusmessages/getcommeventlog.h b/omodscan/modbusmessages/getcommeventlog.h index b15d0aa..8ee3281 100644 --- a/omodscan/modbusmessages/getcommeventlog.h +++ b/omodscan/modbusmessages/getcommeventlog.h @@ -40,6 +40,14 @@ class GetCommEventLogResponse : public ModbusMessage Q_ASSERT((_funcCode & ~QModbusPdu::ExceptionByte) == QModbusPdu::GetCommEventLog); } + /// + /// \brief isValid + /// \return + /// + bool isValid() const override { + return ModbusMessage::isValid() && _data.size() > 7; + } + /// /// \brief byteCount /// \return diff --git a/omodscan/modbusmessages/maskwriteregister.h b/omodscan/modbusmessages/maskwriteregister.h index 5ec2a4b..e1f2208 100644 --- a/omodscan/modbusmessages/maskwriteregister.h +++ b/omodscan/modbusmessages/maskwriteregister.h @@ -21,6 +21,14 @@ class MaskWriteRegisterRequest : public ModbusMessage Q_ASSERT((_funcCode & ~QModbusPdu::ExceptionByte) == QModbusPdu::MaskWriteRegister); } + /// + /// \brief isValid + /// \return + /// + bool isValid() const override { + return ModbusMessage::isValid() && _data.size() == 6; + } + /// /// \brief address /// \return @@ -64,6 +72,14 @@ class MaskWriteRegisterResponse : public ModbusMessage Q_ASSERT((_funcCode & ~QModbusPdu::ExceptionByte) == QModbusPdu::MaskWriteRegister); } + /// + /// \brief isValid + /// \return + /// + bool isValid() const override { + return ModbusMessage::isValid() && _data.size() == 6; + } + /// /// \brief address /// \return diff --git a/omodscan/modbusmessages/modbusmessage.h b/omodscan/modbusmessages/modbusmessage.h index 0405417..7fbab0b 100644 --- a/omodscan/modbusmessages/modbusmessage.h +++ b/omodscan/modbusmessages/modbusmessage.h @@ -27,6 +27,7 @@ class ModbusMessage ,_timestamp(timestamp) ,_deviceId(deviceId) ,_request(request) + ,_isValid(pdu.isValid()) { } @@ -50,7 +51,7 @@ class ModbusMessage /// \return /// virtual bool isValid() const { - return _deviceId >= 0 && !_data.isEmpty(); + return _deviceId >= 0 && _isValid; } /// @@ -107,11 +108,7 @@ class ModbusMessage /// \return /// QString toString(DataDisplayMode mode) const { - QByteArray rawData; - rawData.push_back(_deviceId); - rawData.push_back(_funcCode); - rawData.push_back(_data); - return formatByteArray(mode, rawData); + return formatByteArray(mode, *this); } /// @@ -123,6 +120,17 @@ class ModbusMessage return _data; } + /// + /// \brief operator QByteArray + /// + operator QByteArray() const { + QByteArray data; + data.push_back(_deviceId); + data.push_back(_funcCode); + data.push_back(_data); + return data; + } + protected: const QByteArray _data; const quint8 _funcCode; @@ -132,6 +140,7 @@ class ModbusMessage const QDateTime _timestamp; const int _deviceId; const bool _request; + const bool _isValid; }; Q_DECLARE_METATYPE(const ModbusMessage*) diff --git a/omodscan/modbusmessages/readcoils.h b/omodscan/modbusmessages/readcoils.h index cf53a2f..4c03a48 100644 --- a/omodscan/modbusmessages/readcoils.h +++ b/omodscan/modbusmessages/readcoils.h @@ -22,6 +22,14 @@ class ReadCoilsRequest : public ModbusMessage Q_ASSERT((_funcCode & ~QModbusPdu::ExceptionByte) == QModbusPdu::ReadCoils); } + /// + /// \brief isValid + /// \return + /// + bool isValid() const override { + return ModbusMessage::isValid() && _data.size() == 4; + } + /// /// \brief startAddress /// \return @@ -57,6 +65,14 @@ class ReadCoilsResponse : public ModbusMessage Q_ASSERT((_funcCode & ~QModbusPdu::ExceptionByte) == QModbusPdu::ReadCoils); } + /// + /// \brief isValid + /// \return + /// + bool isValid() const override { + return ModbusMessage::isValid() && _data.size() > 1; + } + /// /// \brief byteCount /// \return diff --git a/omodscan/modbusmessages/readdiscreteinputs.h b/omodscan/modbusmessages/readdiscreteinputs.h index 2926924..974cf1d 100644 --- a/omodscan/modbusmessages/readdiscreteinputs.h +++ b/omodscan/modbusmessages/readdiscreteinputs.h @@ -21,6 +21,14 @@ class ReadDiscreteInputsRequest : public ModbusMessage Q_ASSERT((_funcCode & ~QModbusPdu::ExceptionByte) == QModbusPdu::ReadDiscreteInputs); } + /// + /// \brief isValid + /// \return + /// + bool isValid() const override { + return ModbusMessage::isValid() && _data.size() == 4; + } + /// /// \brief startAddress /// \return @@ -56,6 +64,14 @@ class ReadDiscreteInputsResponse : public ModbusMessage Q_ASSERT((_funcCode & ~QModbusPdu::ExceptionByte) == QModbusPdu::ReadDiscreteInputs); } + /// + /// \brief isValid + /// \return + /// + bool isValid() const override { + return ModbusMessage::isValid() && _data.size() > 1; + } + /// /// \brief byteCount /// \return diff --git a/omodscan/modbusmessages/readexceptionstatus.h b/omodscan/modbusmessages/readexceptionstatus.h index a95972e..90fb570 100644 --- a/omodscan/modbusmessages/readexceptionstatus.h +++ b/omodscan/modbusmessages/readexceptionstatus.h @@ -40,6 +40,14 @@ class ReadExceptionStatusResponse : public ModbusMessage Q_ASSERT((_funcCode & ~QModbusPdu::ExceptionByte) == QModbusPdu::ReadExceptionStatus); } + /// + /// \brief isValid + /// \return + /// + bool isValid() const override { + return ModbusMessage::isValid() && _data.size() == 1; + } + /// /// \brief outputData /// \return diff --git a/omodscan/modbusmessages/readfifoqueue.h b/omodscan/modbusmessages/readfifoqueue.h index 31afff8..c4bf519 100644 --- a/omodscan/modbusmessages/readfifoqueue.h +++ b/omodscan/modbusmessages/readfifoqueue.h @@ -21,6 +21,14 @@ class ReadFifoQueueRequest : public ModbusMessage Q_ASSERT((_funcCode & ~QModbusPdu::ExceptionByte) == QModbusPdu::ReadFifoQueue); } + /// + /// \brief isValid + /// \return + /// + bool isValid() const override { + return ModbusMessage::isValid() && _data.size() == 2; + } + /// /// \brief fifoAddress /// \return @@ -48,6 +56,14 @@ class ReadFifoQueueResponse : public ModbusMessage Q_ASSERT((_funcCode & ~QModbusPdu::ExceptionByte) == QModbusPdu::ReadFifoQueue); } + /// + /// \brief isValid + /// \return + /// + bool isValid() const override { + return ModbusMessage::isValid() && _data.size() > 5; + } + /// /// \brief byteCount /// \return diff --git a/omodscan/modbusmessages/readfilerecord.h b/omodscan/modbusmessages/readfilerecord.h index 4f57aa4..feab598 100644 --- a/omodscan/modbusmessages/readfilerecord.h +++ b/omodscan/modbusmessages/readfilerecord.h @@ -21,6 +21,14 @@ class ReadFileRecordRequest : public ModbusMessage Q_ASSERT((_funcCode & ~QModbusPdu::ExceptionByte) == QModbusPdu::ReadFileRecord); } + /// + /// \brief isValid + /// \return + /// + bool isValid() const override { + return ModbusMessage::isValid() && _data.size() > 1; + } + /// /// \brief byteCount /// \return @@ -56,6 +64,14 @@ class ReadFileRecordResponse : public ModbusMessage Q_ASSERT((_funcCode & ~QModbusPdu::ExceptionByte) == QModbusPdu::ReadFileRecord); } + /// + /// \brief isValid + /// \return + /// + bool isValid() const override { + return ModbusMessage::isValid() && _data.size() > 1; + } + /// /// \brief byteCount /// \return diff --git a/omodscan/modbusmessages/readholdingregisters.h b/omodscan/modbusmessages/readholdingregisters.h index 8047021..d62a048 100644 --- a/omodscan/modbusmessages/readholdingregisters.h +++ b/omodscan/modbusmessages/readholdingregisters.h @@ -21,6 +21,14 @@ class ReadHoldingRegistersRequest : public ModbusMessage Q_ASSERT((_funcCode & ~QModbusPdu::ExceptionByte) == QModbusPdu::ReadHoldingRegisters); } + /// + /// \brief isValid + /// \return + /// + bool isValid() const override { + return ModbusMessage::isValid() && _data.size() == 4; + } + /// /// \brief startAddress /// \return @@ -56,6 +64,14 @@ class ReadHoldingRegistersResponse : public ModbusMessage Q_ASSERT((_funcCode & ~QModbusPdu::ExceptionByte) == QModbusPdu::ReadHoldingRegisters); } + /// + /// \brief isValid + /// \return + /// + bool isValid() const override { + return ModbusMessage::isValid() && _data.size() > 1; + } + /// /// \brief byteCount /// \return diff --git a/omodscan/modbusmessages/readinputregisters.h b/omodscan/modbusmessages/readinputregisters.h index 701937e..7d5ab4b 100644 --- a/omodscan/modbusmessages/readinputregisters.h +++ b/omodscan/modbusmessages/readinputregisters.h @@ -21,6 +21,14 @@ class ReadInputRegistersRequest : public ModbusMessage Q_ASSERT((_funcCode & ~QModbusPdu::ExceptionByte) == QModbusPdu::ReadInputRegisters); } + /// + /// \brief isValid + /// \return + /// + bool isValid() const override { + return ModbusMessage::isValid() && _data.size() == 4; + } + /// /// \brief startAddress /// \return @@ -56,6 +64,14 @@ class ReadInputRegistersResponse : public ModbusMessage Q_ASSERT((_funcCode & ~QModbusPdu::ExceptionByte) == QModbusPdu::ReadInputRegisters); } + /// + /// \brief isValid + /// \return + /// + bool isValid() const override { + return ModbusMessage::isValid() && _data.size() > 1; + } + /// /// \brief byteCount /// \return diff --git a/omodscan/modbusmessages/readwritemultipleregisters.h b/omodscan/modbusmessages/readwritemultipleregisters.h index 6f756a6..3a5954c 100644 --- a/omodscan/modbusmessages/readwritemultipleregisters.h +++ b/omodscan/modbusmessages/readwritemultipleregisters.h @@ -21,6 +21,14 @@ class ReadWriteMultipleRegistersRequest : public ModbusMessage Q_ASSERT((_funcCode & ~QModbusPdu::ExceptionByte) == QModbusPdu::ReadWriteMultipleRegisters); } + /// + /// \brief isValid + /// \return + /// + bool isValid() const override { + return ModbusMessage::isValid() && _data.size() > 9; + } + /// /// \brief readStartAddress /// \return @@ -88,6 +96,14 @@ class ReadWriteMultipleRegistersResponse : public ModbusMessage Q_ASSERT((_funcCode & ~QModbusPdu::ExceptionByte) == QModbusPdu::ReadWriteMultipleRegisters); } + /// + /// \brief isValid + /// \return + /// + bool isValid() const override { + return ModbusMessage::isValid() && _data.size() > 1; + } + /// /// \brief byteCount /// \return diff --git a/omodscan/modbusmessages/reportserverid.h b/omodscan/modbusmessages/reportserverid.h index 56cfd72..49869da 100644 --- a/omodscan/modbusmessages/reportserverid.h +++ b/omodscan/modbusmessages/reportserverid.h @@ -40,6 +40,14 @@ class ReportServerIdResponse : public ModbusMessage Q_ASSERT((_funcCode & ~QModbusPdu::ExceptionByte) == QModbusPdu::ReportServerId); } + /// + /// \brief isValid + /// \return + /// + bool isValid() const override { + return ModbusMessage::isValid() && _data.size() > 1; + } + /// /// \brief byteCount /// \return diff --git a/omodscan/modbusmessages/writefilerecord.h b/omodscan/modbusmessages/writefilerecord.h index f8e7b70..36f74e7 100644 --- a/omodscan/modbusmessages/writefilerecord.h +++ b/omodscan/modbusmessages/writefilerecord.h @@ -21,6 +21,14 @@ class WriteFileRecordRequest : public ModbusMessage Q_ASSERT((_funcCode & ~QModbusPdu::ExceptionByte) == QModbusPdu::WriteFileRecord); } + /// + /// \brief isValid + /// \return + /// + bool isValid() const override { + return ModbusMessage::isValid() && _data.size() > 1; + } + /// /// \brief length /// \return @@ -56,6 +64,14 @@ class WriteFileRecordResponse : public ModbusMessage Q_ASSERT((_funcCode & ~QModbusPdu::ExceptionByte) == QModbusPdu::WriteFileRecord); } + /// + /// \brief isValid + /// \return + /// + bool isValid() const override { + return ModbusMessage::isValid() && _data.size() > 1; + } + /// /// \brief length /// \return diff --git a/omodscan/modbusmessages/writemultiplecoils.h b/omodscan/modbusmessages/writemultiplecoils.h index 0308461..f621d4a 100644 --- a/omodscan/modbusmessages/writemultiplecoils.h +++ b/omodscan/modbusmessages/writemultiplecoils.h @@ -21,6 +21,14 @@ class WriteMultipleCoilsRequest : public ModbusMessage Q_ASSERT((_funcCode & ~QModbusPdu::ExceptionByte) == QModbusPdu::WriteMultipleCoils); } + /// + /// \brief isValid + /// \return + /// + bool isValid() const override { + return ModbusMessage::isValid() && _data.size() > 5; + } + /// /// \brief startAddress /// \return @@ -72,6 +80,14 @@ class WriteMultipleCoilsResponse : public ModbusMessage Q_ASSERT((_funcCode & ~QModbusPdu::ExceptionByte) == QModbusPdu::WriteMultipleCoils); } + /// + /// \brief isValid + /// \return + /// + bool isValid() const override { + return ModbusMessage::isValid() && _data.size() == 4; + } + /// /// \brief startAddress /// \return diff --git a/omodscan/modbusmessages/writemultipleregisters.h b/omodscan/modbusmessages/writemultipleregisters.h index 5952515..5a64870 100644 --- a/omodscan/modbusmessages/writemultipleregisters.h +++ b/omodscan/modbusmessages/writemultipleregisters.h @@ -21,6 +21,14 @@ class WriteMultipleRegistersRequest : public ModbusMessage Q_ASSERT((_funcCode & ~QModbusPdu::ExceptionByte) == QModbusPdu::WriteMultipleRegisters); } + /// + /// \brief isValid + /// \return + /// + bool isValid() const override { + return ModbusMessage::isValid() && _data.size() > 5; + } + /// /// \brief startAddress /// \return @@ -72,6 +80,14 @@ class WriteMultipleRegistersResponse : public ModbusMessage Q_ASSERT((_funcCode & ~QModbusPdu::ExceptionByte) == QModbusPdu::WriteMultipleRegisters); } + /// + /// \brief isValid + /// \return + /// + bool isValid() const override { + return ModbusMessage::isValid() && _data.size() == 4; + } + /// /// \brief startAddress /// \return diff --git a/omodscan/modbusmessages/writesinglecoil.h b/omodscan/modbusmessages/writesinglecoil.h index de26fca..c119fd5 100644 --- a/omodscan/modbusmessages/writesinglecoil.h +++ b/omodscan/modbusmessages/writesinglecoil.h @@ -21,6 +21,14 @@ class WriteSingleCoilRequest : public ModbusMessage Q_ASSERT((_funcCode & ~QModbusPdu::ExceptionByte) == QModbusPdu::WriteSingleCoil); } + /// + /// \brief isValid + /// \return + /// + bool isValid() const override { + return ModbusMessage::isValid() && _data.size() == 4; + } + /// /// \brief address /// \return @@ -56,6 +64,14 @@ class WriteSingleCoilResponse : public ModbusMessage Q_ASSERT((_funcCode & ~QModbusPdu::ExceptionByte) == QModbusPdu::WriteSingleCoil); } + /// + /// \brief isValid + /// \return + /// + bool isValid() const override { + return ModbusMessage::isValid() && _data.size() == 4; + } + /// /// \brief address /// \return diff --git a/omodscan/modbusmessages/writesingleregister.h b/omodscan/modbusmessages/writesingleregister.h index a2b73c8..00ece7e 100644 --- a/omodscan/modbusmessages/writesingleregister.h +++ b/omodscan/modbusmessages/writesingleregister.h @@ -21,6 +21,14 @@ class WriteSingleRegisterRequest : public ModbusMessage Q_ASSERT((_funcCode & ~QModbusPdu::ExceptionByte) == QModbusPdu::WriteSingleRegister); } + /// + /// \brief isValid + /// \return + /// + bool isValid() const override { + return ModbusMessage::isValid() && _data.size() == 4; + } + /// /// \brief address /// \return @@ -56,6 +64,14 @@ class WriteSingleRegisterResponse : public ModbusMessage Q_ASSERT((_funcCode & ~QModbusPdu::ExceptionByte) == QModbusPdu::WriteSingleRegister); } + /// + /// \brief isValid + /// \return + /// + bool isValid() const override { + return ModbusMessage::isValid() && _data.size() == 4; + } + /// /// \brief address /// \return From 96bb3642d53c0fb48e3f9a4bfdc7ac31bd168292 Mon Sep 17 00:00:00 2001 From: sanny32 Date: Tue, 3 Oct 2023 16:22:44 +0300 Subject: [PATCH 29/90] Write modbus log from other dialogs in active window --- omodscan/dialogs/dialogusermsg.cpp | 8 ++-- omodscan/formmodsca.cpp | 62 ++++++++++++++++++++++-------- omodscan/formmodsca.h | 11 +++++- omodscan/mainwindow.cpp | 7 +++- 4 files changed, 66 insertions(+), 22 deletions(-) diff --git a/omodscan/dialogs/dialogusermsg.cpp b/omodscan/dialogs/dialogusermsg.cpp index 51c8ec5..d11812a 100644 --- a/omodscan/dialogs/dialogusermsg.cpp +++ b/omodscan/dialogs/dialogusermsg.cpp @@ -85,15 +85,15 @@ void DialogUserMsg::on_modbusReply(QModbusReply* reply) { if(!reply) return; - if(reply->error() != QModbusDevice::NoError && - reply->error() != QModbusDevice::ProtocolError) + if(0 != reply->property("RequestId").toInt()) { - QMessageBox::warning(this, windowTitle(), reply->errorString()); return; } - if(0 != reply->property("RequestId").toInt()) + if(reply->error() != QModbusDevice::NoError && + reply->error() != QModbusDevice::ProtocolError) { + QMessageBox::warning(this, windowTitle(), reply->errorString()); return; } diff --git a/omodscan/formmodsca.cpp b/omodscan/formmodsca.cpp index 6b01860..eacefa6 100644 --- a/omodscan/formmodsca.cpp +++ b/omodscan/formmodsca.cpp @@ -537,6 +537,20 @@ bool FormModSca::isValidReply(const QModbusReply* reply) const return false; } +/// +/// \brief FormModSca::logRequest +/// \param requestId +/// \param deviceId +/// \param request +/// +void FormModSca::logRequest(int requestId, int deviceId, const QModbusRequest& request) +{ + if(requestId == _formId && deviceId == ui->lineEditDeviceId->value()) + ui->outputWidget->updateTraffic(request, deviceId); + else if(requestId == 0 && isActive()) + ui->outputWidget->updateTraffic(request, deviceId); +} + /// /// \brief FormModSca::on_modbusRequest /// \param requestId @@ -545,8 +559,7 @@ bool FormModSca::isValidReply(const QModbusReply* reply) const /// void FormModSca::on_modbusRequest(int requestId, int deviceId, const QModbusRequest& request) { - if(requestId != _formId) - return; + logRequest(requestId, deviceId, request); switch(request.functionCode()) { @@ -554,14 +567,36 @@ void FormModSca::on_modbusRequest(int requestId, int deviceId, const QModbusRequ case QModbusPdu::ReadDiscreteInputs: case QModbusPdu::ReadHoldingRegisters: case QModbusPdu::ReadInputRegisters: - ui->statisticWidget->increaseNumberOfPolls(); + if(requestId == _formId) + ui->statisticWidget->increaseNumberOfPolls(); break; default: break; } +} + +/// +/// \brief FormModSca::logReply +/// \param reply +/// +void FormModSca::logReply(const QModbusReply* reply) +{ + if(!reply) return; + + if(reply->error() != QModbusDevice::NoError && + reply->error() != QModbusDevice::ProtocolError) + { + return; + } + + const auto deviceId = reply->serverAddress(); + const auto requestId = reply->property("RequestId").toInt(); - ui->outputWidget->updateTraffic(request, deviceId); + if(requestId == _formId && deviceId == ui->lineEditDeviceId->value()) + ui->outputWidget->updateTraffic(reply->rawResult(), reply->serverAddress()); + else if(requestId == 0 && isActive()) + ui->outputWidget->updateTraffic(reply->rawResult(), reply->serverAddress()); } /// @@ -572,14 +607,10 @@ void FormModSca::on_modbusReply(QModbusReply* reply) { if(!reply) return; - const auto requestId = reply->property("RequestId").toInt(); - if(requestId != _formId) - return; + logReply(reply); - const auto data = reply->result(); const auto response = reply->rawResult(); const bool hasError = reply->error() != QModbusDevice::NoError; - const bool hasProtocolError = reply->error() == QModbusDevice::ProtocolError; switch(response.functionCode()) { @@ -587,17 +618,16 @@ void FormModSca::on_modbusReply(QModbusReply* reply) case QModbusRequest::ReadDiscreteInputs: case QModbusRequest::ReadInputRegisters: case QModbusRequest::ReadHoldingRegisters: - if(!hasError || hasProtocolError) - ui->outputWidget->updateTraffic(response, reply->serverAddress()); break; default: - if(!hasError || hasProtocolError) - ui->outputWidget->updateTraffic(response, reply->serverAddress()); if(!hasError) beginUpdate(); - return; + break; } + if(reply->property("RequestId").toInt() != _formId) + return; + if (!hasError) { if(!isValidReply(reply)) @@ -606,12 +636,12 @@ void FormModSca::on_modbusReply(QModbusReply* reply) } else { - ui->outputWidget->updateData(data); + ui->outputWidget->updateData(reply->result()); ui->outputWidget->setStatus(QString()); ui->statisticWidget->increaseValidSlaveResponses(); } } - else if (hasProtocolError) + else if (reply->error() == QModbusDevice::ProtocolError) { const auto ex = ModbusException(response.exceptionCode()); const auto errorString = QString("%1 (%2)").arg(ex, formatByteValue(DataDisplayMode::Hex, ex)); diff --git a/omodscan/formmodsca.h b/omodscan/formmodsca.h index d271800..03c9438 100644 --- a/omodscan/formmodsca.h +++ b/omodscan/formmodsca.h @@ -34,7 +34,13 @@ class FormModSca : public QWidget explicit FormModSca(int id, ModbusClient& client, QSharedPointer simulator, MainWindow* parent); ~FormModSca(); - int formId() const { return _formId; } + int formId() const { + return _formId; + } + + bool isActive() const { + return property("isActive").toBool(); + } QString filename() const; void setFilename(const QString& filename); @@ -117,6 +123,9 @@ private slots: void beginUpdate(); bool isValidReply(const QModbusReply* reply) const; + void logReply(const QModbusReply* reply); + void logRequest(int requestId, int deviceId, const QModbusRequest& request); + private: Ui::FormModSca *ui; int _formId; diff --git a/omodscan/mainwindow.cpp b/omodscan/mainwindow.cpp index 4ca5b18..d0ffd62 100644 --- a/omodscan/mainwindow.cpp +++ b/omodscan/mainwindow.cpp @@ -277,6 +277,7 @@ void MainWindow::on_actionNew_triggered() frm->setByteOrder(cur->byteOrder()); frm->setDisplayMode(cur->displayMode()); frm->setDataDisplayMode(cur->dataDisplayMode()); + frm->setDisplayDefinition(cur->displayDefinition()); frm->setFont(cur->font()); frm->setStatusColor(cur->statusColor()); @@ -936,6 +937,7 @@ void MainWindow::updateMenuWindow() for(auto&& wnd : ui->mdiArea->subWindowList()) { wnd->setProperty("isActive", wnd == activeWnd); + wnd->widget()->setProperty("isActive", wnd == activeWnd); } _windowActionList->update(); } @@ -946,7 +948,10 @@ void MainWindow::updateMenuWindow() /// void MainWindow::windowActivate(QMdiSubWindow* wnd) { - if(wnd) ui->mdiArea->setActiveSubWindow(wnd); + if(wnd) + { + ui->mdiArea->setActiveSubWindow(wnd); + } } /// From 5e41448e84b923d62d68b82b92f938d1fc43e137 Mon Sep 17 00:00:00 2001 From: sanny32 Date: Tue, 3 Oct 2023 16:50:30 +0300 Subject: [PATCH 30/90] Developing new log view --- omodscan/formmodsca.cpp | 13 +++++++++++++ omodscan/mainwindow.cpp | 5 ++--- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/omodscan/formmodsca.cpp b/omodscan/formmodsca.cpp index eacefa6..8dfbbc0 100644 --- a/omodscan/formmodsca.cpp +++ b/omodscan/formmodsca.cpp @@ -134,13 +134,26 @@ DisplayDefinition FormModSca::displayDefinition() const void FormModSca::setDisplayDefinition(const DisplayDefinition& dd) { _timer.setInterval(dd.ScanRate); + + ui->lineEditDeviceId->blockSignals(true); ui->lineEditDeviceId->setValue(dd.DeviceId); + ui->lineEditDeviceId->blockSignals(false); + + ui->lineEditAddress->blockSignals(true); ui->lineEditAddress->setValue(dd.PointAddress); + ui->lineEditAddress->blockSignals(false); + + ui->lineEditLength->blockSignals(true); ui->lineEditLength->setValue(dd.Length); + ui->lineEditLength->blockSignals(false); + + ui->comboBoxModbusPointType->blockSignals(true); ui->comboBoxModbusPointType->setCurrentPointType(dd.PointType); + ui->comboBoxModbusPointType->blockSignals(false); ui->outputWidget->setStatus(tr("Data Uninitialized")); ui->outputWidget->setup(dd, _dataSimulator->simulationMap(dd.DeviceId)); + beginUpdate(); } diff --git a/omodscan/mainwindow.cpp b/omodscan/mainwindow.cpp index d0ffd62..469439b 100644 --- a/omodscan/mainwindow.cpp +++ b/omodscan/mainwindow.cpp @@ -738,9 +738,8 @@ void MainWindow::on_actionUserMsg_triggered() break; } - auto dlg = new DialogUserMsg(dd.DeviceId, func, mode, _modbusClient, this); - dlg->setAttribute(Qt::WA_DeleteOnClose, true); - dlg->show(); + DialogUserMsg dlg(dd.DeviceId, func, mode, _modbusClient, this); + dlg.exec(); } /// From cafffcaafa306d973dad8926fe5648a527fa7070 Mon Sep 17 00:00:00 2001 From: sanny32 Date: Wed, 4 Oct 2023 11:39:44 +0300 Subject: [PATCH 31/90] Correct NumericLineEdit to set value --- omodscan/controls/numericlineedit.cpp | 34 +++++++++++++++++++-------- 1 file changed, 24 insertions(+), 10 deletions(-) diff --git a/omodscan/controls/numericlineedit.cpp b/omodscan/controls/numericlineedit.cpp index 1a332d6..981fbc9 100644 --- a/omodscan/controls/numericlineedit.cpp +++ b/omodscan/controls/numericlineedit.cpp @@ -126,12 +126,14 @@ void NumericLineEdit::internalSetValue(QVariant value) if(_paddingZeroes) { const auto text = QStringLiteral("%1").arg(value.toInt(), _paddingZeroWidth, 10, QLatin1Char('0')); - QLineEdit::setText(text); + if(text != QLineEdit::text()) + QLineEdit::setText(text); } else { const auto text = QString::number(value.toInt()); - QLineEdit::setText(text); + if(text != QLineEdit::text()) + QLineEdit::setText(text); } break; @@ -139,12 +141,14 @@ void NumericLineEdit::internalSetValue(QVariant value) value = qBound(_minValue.toUInt(), value.toUInt(), _maxValue.toUInt()); if(_paddingZeroes) { - const auto text = QStringLiteral("%1").arg(value.toUInt(), _paddingZeroWidth, 10, QLatin1Char('0')); + const auto text = QStringLiteral("%1").arg(value.toUInt(), _paddingZeroWidth, 10, QLatin1Char('0')); + if(text != QLineEdit::text()) QLineEdit::setText(text); } else { - const auto text = QString::number(value.toUInt()); + const auto text = QString::number(value.toUInt()); + if(text != QLineEdit::text()) QLineEdit::setText(text); } break; @@ -153,24 +157,34 @@ void NumericLineEdit::internalSetValue(QVariant value) value = qBound(_minValue.toInt() > 0 ? _minValue.toUInt() : 0, value.toUInt(), _maxValue.toUInt()); if(_paddingZeroes) { - const auto text = QStringLiteral("%1").arg(value.toUInt(), _paddingZeroWidth, 16, QLatin1Char('0')); - QLineEdit::setText(text.toUpper()); + const auto text = QStringLiteral("%1").arg(value.toUInt(), _paddingZeroWidth, 16, QLatin1Char('0')).toUpper(); + if(text != QLineEdit::text()) + QLineEdit::setText(text); } else { - const auto text = QString("%1").arg(value.toUInt(), -1, 16); - QLineEdit::setText(text.toUpper()); + const auto text = QString("%1").arg(value.toUInt(), -1, 16).toUpper(); + if(text != QLineEdit::text()) + QLineEdit::setText(text); } break; case FloatMode: + { value = qBound(_minValue.toFloat(), value.toFloat(), _maxValue.toFloat()); - QLineEdit::setText(QLocale().toString(value.toFloat())); + const auto text = QLocale().toString(value.toFloat()); + if(text != QLineEdit::text()) + QLineEdit::setText(text); + } break; case DoubleMode: + { value = qBound(_minValue.toDouble(), value.toDouble(), _maxValue.toDouble()); - QLineEdit::setText(QLocale().toString(value.toDouble())); + const auto text = QLocale().toString(value.toFloat()); + if(text != QLineEdit::text()) + QLineEdit::setText(text); + } break; } From 56cf904fd91b92aa3238c1ae4734d4bac50315ac Mon Sep 17 00:00:00 2001 From: sanny32 Date: Wed, 4 Oct 2023 11:40:22 +0300 Subject: [PATCH 32/90] Correct User Msg dialog behavior --- omodscan/controls/bytelistlineedit.cpp | 205 --------------------- omodscan/controls/bytelistlineedit.h | 49 ----- omodscan/controls/bytelisttextedit.cpp | 239 +++++++++++++++++++++++++ omodscan/controls/bytelisttextedit.h | 53 ++++++ omodscan/dialogs/dialogusermsg.cpp | 16 +- omodscan/dialogs/dialogusermsg.ui | 91 ++++++---- omodscan/omodscan.pro | 4 +- 7 files changed, 362 insertions(+), 295 deletions(-) delete mode 100644 omodscan/controls/bytelistlineedit.cpp delete mode 100644 omodscan/controls/bytelistlineedit.h create mode 100644 omodscan/controls/bytelisttextedit.cpp create mode 100644 omodscan/controls/bytelisttextedit.h diff --git a/omodscan/controls/bytelistlineedit.cpp b/omodscan/controls/bytelistlineedit.cpp deleted file mode 100644 index 9a3ccd5..0000000 --- a/omodscan/controls/bytelistlineedit.cpp +++ /dev/null @@ -1,205 +0,0 @@ -#include -#include "formatutils.h" -#include "bytelistlineedit.h" - -/// -/// \brief ByteListLineEdit::ByteListLineEdit -/// \param parent -/// -ByteListLineEdit::ByteListLineEdit(QWidget* parent) - :QLineEdit(parent) -{ - setInputMode(DecMode); - - connect(this, &QLineEdit::editingFinished, this, &ByteListLineEdit::on_editingFinished); - connect(this, &QLineEdit::textChanged, this, &ByteListLineEdit::on_textChanged); -} - -/// -/// \brief ByteListLineEdit::ByteListLineEdit -/// \param mode -/// \param parent -/// -ByteListLineEdit::ByteListLineEdit(InputMode mode, QWidget *parent) - :QLineEdit(parent) -{ - setInputMode(mode); - - connect(this, &QLineEdit::editingFinished, this, &ByteListLineEdit::on_editingFinished); - connect(this, &QLineEdit::textChanged, this, &ByteListLineEdit::on_textChanged); -} - -/// -/// \brief ByteListLineEdit::value -/// \return -/// -QByteArray ByteListLineEdit::value() const -{ - return _value; -} - -/// -/// \brief ByteListLineEdit::setValue -/// \param value -/// -void ByteListLineEdit::setValue(const QByteArray& value) -{ - switch(_inputMode) - { - case DecMode: - { - QLineEdit::setText(formatByteArray(DataDisplayMode::Decimal, value)); - QLineEdit::setCursorPosition(0); - } - break; - - case HexMode: - { - QLineEdit::setText(formatByteArray(DataDisplayMode::Hex, value)); - QLineEdit::setCursorPosition(0); - } - break; - } - - if(value != _value) - { - _value = value; - emit valueChanged(_value); - } -} - -/// -/// \brief ByteListLineEdit::inputMode -/// \return -/// -ByteListLineEdit::InputMode ByteListLineEdit::inputMode() const -{ - return _inputMode; -} - -/// -/// \brief ByteListLineEdit::setInputMode -/// \param mode -/// -void ByteListLineEdit::setInputMode(InputMode mode) -{ - _inputMode = mode; - - setValidator(nullptr); - switch(mode) - { - case DecMode: - setValidator(new QRegularExpressionValidator(QRegularExpression("(?:[0-9]{1,2}[\\s]{0,1})*"), this)); - break; - - case HexMode: - setValidator(new QRegularExpressionValidator(QRegularExpression("(?:[0-9a-fA-F]{1,2}[\\s]{0,1})*"), this)); - break; - } - setValue(_value); -} - -/// -/// \brief ByteListLineEdit::setText -/// \param text -/// -void ByteListLineEdit::setText(const QString& text) -{ - QLineEdit::setText(text); - updateValue(); -} - -/// -/// \brief ByteListLineEdit::focusOutEvent -/// \param event -/// -void ByteListLineEdit::focusOutEvent(QFocusEvent* event) -{ - updateValue(); - QLineEdit::focusOutEvent(event); -} - -/// -/// \brief ByteListLineEdit::on_editingFinished -/// -void ByteListLineEdit::on_editingFinished() -{ - updateValue(); -} - -/// -/// \brief ByteListLineEdit::on_textChanged -/// \param text -/// -void ByteListLineEdit::on_textChanged(const QString& text) -{ - QByteArray value; - switch(_inputMode) - { - case DecMode: - { - for(auto&& s : text.split(' ')) - { - bool ok; - const quint8 v = s.trimmed().toUInt(&ok); - if(ok) value.push_back(v); - } - } - break; - - case HexMode: - { - for(auto&& s : text.split(' ')) - { - bool ok; - const quint8 v = s.trimmed().toUInt(&ok, 16); - if(ok) value.push_back(v); - } - } - break; - } - - if(!value.isEmpty() && value != _value) - { - _value = value; - emit valueChanged(_value); - } -} - -/// -/// \brief ByteListLineEdit::updateValue -/// -void ByteListLineEdit::updateValue() -{ - QByteArray value; - switch(_inputMode) - { - case DecMode: - { - for(auto&& s : text().split(' ')) - { - bool ok; - const quint8 v = s.trimmed().toUInt(&ok); - if(ok) value.push_back(v); - } - - if(!value.isEmpty()) setValue(value); - else setValue(_value); - } - break; - - case HexMode: - { - for(auto&& s : text().split(' ')) - { - bool ok; - const quint8 v = s.trimmed().toUInt(&ok, 16); - if(ok) value.push_back(v); - } - - if(!value.isEmpty()) setValue(value); - else setValue(_value); - } - break; - } -} diff --git a/omodscan/controls/bytelistlineedit.h b/omodscan/controls/bytelistlineedit.h deleted file mode 100644 index cf7711c..0000000 --- a/omodscan/controls/bytelistlineedit.h +++ /dev/null @@ -1,49 +0,0 @@ -#ifndef BYTELISTLINEEDIT_H -#define BYTELISTLINEEDIT_H - -#include - -/// -/// \brief The ByteListLineEdit class -/// -class ByteListLineEdit : public QLineEdit -{ - Q_OBJECT - -public: - enum InputMode - { - DecMode = 0, - HexMode - }; - - explicit ByteListLineEdit(QWidget* parent = nullptr); - explicit ByteListLineEdit(InputMode mode, QWidget *parent = nullptr); - - QByteArray value() const; - void setValue(const QByteArray& value); - - InputMode inputMode() const; - void setInputMode(InputMode mode); - - void setText(const QString& text); - -signals: - void valueChanged(const QByteArray& value); - -protected: - void focusOutEvent(QFocusEvent*) override; - -private slots: - void on_editingFinished(); - void on_textChanged(const QString& text); - -private: - void updateValue(); - -private: - InputMode _inputMode; - QByteArray _value; -}; - -#endif // BYTELISTLINEEDIT_H diff --git a/omodscan/controls/bytelisttextedit.cpp b/omodscan/controls/bytelisttextedit.cpp new file mode 100644 index 0000000..cb91ed0 --- /dev/null +++ b/omodscan/controls/bytelisttextedit.cpp @@ -0,0 +1,239 @@ +#include +#include "formatutils.h" +#include "bytelisttextedit.h" + +/// +/// \brief ByteListTextEdit::ByteListTextEdit +/// \param parent +/// +ByteListTextEdit::ByteListTextEdit(QWidget* parent) + :QPlainTextEdit(parent) + ,_separator(' ') + ,_validator(nullptr) +{ + setInputMode(DecMode); + connect(this, &QPlainTextEdit::textChanged, this, &ByteListTextEdit::on_textChanged); +} + +/// +/// \brief ByteListTextEdit::ByteListTextEdit +/// \param mode +/// \param parent +/// +ByteListTextEdit::ByteListTextEdit(InputMode mode, QWidget *parent) + :QPlainTextEdit(parent) + ,_separator(' ') + ,_validator(nullptr) +{ + setInputMode(mode); + connect(this, &QPlainTextEdit::textChanged, this, &ByteListTextEdit::on_textChanged); +} + +/// +/// \brief ByteListTextEdit::value +/// \return +/// +QByteArray ByteListTextEdit::value() const +{ + return _value; +} + +/// +/// \brief ByteListTextEdit::setValue +/// \param value +/// +void ByteListTextEdit::setValue(const QByteArray& value) +{ + switch(_inputMode) + { + case DecMode: + { + const auto text = formatByteArray(DataDisplayMode::Hex, value); + if(text != toPlainText()) + setPlainText(formatByteArray(DataDisplayMode::Decimal, value)); + } + break; + + case HexMode: + { + const auto text = formatByteArray(DataDisplayMode::Hex, value); + if(text != toPlainText()) + setPlainText(formatByteArray(DataDisplayMode::Hex, value)); + } + break; + } + + if(value != _value) + { + _value = value; + emit valueChanged(_value); + } +} + +/// +/// \brief ByteListTextEdit::inputMode +/// \return +/// +ByteListTextEdit::InputMode ByteListTextEdit::inputMode() const +{ + return _inputMode; +} + +/// +/// \brief ByteListTextEdit::setInputMode +/// \param mode +/// +void ByteListTextEdit::setInputMode(InputMode mode) +{ + _inputMode = mode; + + if(_validator) + { + delete _validator; + _validator = nullptr; + } + + const auto sep = (_separator == ' ')? "\\s" : QString(_separator); + switch(mode) + { + case DecMode: + _validator =new QRegularExpressionValidator(QRegularExpression("(?:[0-9]{1,2}[" + sep + "]{0,1})*"), this); + break; + + case HexMode: + _validator = new QRegularExpressionValidator(QRegularExpression("(?:[0-9a-fA-F]{1,2}[" + sep + "]{0,1})*"), this); + break; + } + + setValue(_value); +} + +/// +/// \brief ByteListTextEdit::text +/// \return +/// +QString ByteListTextEdit::text() const +{ + return toPlainText(); +} + +/// +/// \brief ByteListTextEdit::setText +/// \param text +/// +void ByteListTextEdit::setText(const QString& text) +{ + setPlainText(text); + updateValue(); +} + +/// +/// \brief ByteListTextEdit::focusOutEvent +/// \param event +/// +void ByteListTextEdit::focusOutEvent(QFocusEvent* e) +{ + updateValue(); + QPlainTextEdit::focusOutEvent(e); +} + +/// +/// \brief ByteListTextEdit::keyPressEvent +/// \param e +/// +void ByteListTextEdit::keyPressEvent(QKeyEvent *e) +{ + int pos = 0; + auto text = toPlainText() + e->text(); + const auto state = _validator->validate(text, pos); + + if(state == QValidator::Acceptable || + e->key() == Qt::Key_Backspace || + e->key() == Qt::Key_Delete || + e->matches(QKeySequence::Cut) || + e->matches(QKeySequence::Copy) || + e->matches(QKeySequence::Paste) || + e->matches(QKeySequence::Undo) || + e->matches(QKeySequence::Redo) || + e->matches(QKeySequence::SelectAll)) + { + QPlainTextEdit::keyPressEvent(e); + } +} + +/// +/// \brief ByteListTextEdit::on_textChanged +/// +void ByteListTextEdit::on_textChanged() +{ + QByteArray value; + + switch(_inputMode) + { + case DecMode: + { + for(auto&& s : text().split(_separator)) + { + bool ok; + const quint8 v = s.trimmed().toUInt(&ok); + if(ok) value.push_back(v); + } + } + break; + + case HexMode: + { + for(auto&& s : text().split(_separator)) + { + bool ok; + const quint8 v = s.trimmed().toUInt(&ok, 16); + if(ok) value.push_back(v); + } + } + break; + } + + if(value != _value) + { + _value = value; + emit valueChanged(_value); + } +} + +/// +/// \brief ByteListTextEdit::updateValue +/// +void ByteListTextEdit::updateValue() +{ + QByteArray value; + switch(_inputMode) + { + case DecMode: + { + for(auto&& s : text().split(_separator)) + { + bool ok; + const quint8 v = s.trimmed().toUInt(&ok); + if(ok) value.push_back(v); + } + + if(!value.isEmpty()) setValue(value); + else setValue(_value); + } + break; + + case HexMode: + { + for(auto&& s : text().split(_separator)) + { + bool ok; + const quint8 v = s.trimmed().toUInt(&ok, 16); + if(ok) value.push_back(v); + } + + if(!value.isEmpty()) setValue(value); + else setValue(_value); + } + break; + } +} diff --git a/omodscan/controls/bytelisttextedit.h b/omodscan/controls/bytelisttextedit.h new file mode 100644 index 0000000..1b7ea2c --- /dev/null +++ b/omodscan/controls/bytelisttextedit.h @@ -0,0 +1,53 @@ +#ifndef BYTELISTTEXTEDIT_H +#define BYTELISTTEXTEDIT_H + +#include +#include + +/// +/// \brief The ByteListTextEdit class +/// +class ByteListTextEdit : public QPlainTextEdit +{ + Q_OBJECT + +public: + enum InputMode + { + DecMode = 0, + HexMode + }; + + explicit ByteListTextEdit(QWidget* parent = nullptr); + explicit ByteListTextEdit(InputMode mode, QWidget *parent = nullptr); + + QByteArray value() const; + void setValue(const QByteArray& value); + + InputMode inputMode() const; + void setInputMode(InputMode mode); + + QString text() const; + void setText(const QString& text); + +signals: + void valueChanged(const QByteArray& value); + +protected: + void focusOutEvent(QFocusEvent* e) override; + void keyPressEvent(QKeyEvent* e) override; + +private slots: + void on_textChanged(); + +private: + void updateValue(); + +private: + InputMode _inputMode; + QByteArray _value; + QChar _separator; + QValidator* _validator; +}; + +#endif // BYTELISTTEXTEDIT_H diff --git a/omodscan/dialogs/dialogusermsg.cpp b/omodscan/dialogs/dialogusermsg.cpp index d11812a..e671a14 100644 --- a/omodscan/dialogs/dialogusermsg.cpp +++ b/omodscan/dialogs/dialogusermsg.cpp @@ -57,11 +57,11 @@ DialogUserMsg::~DialogUserMsg() /// void DialogUserMsg::accept() { - ui->lineEditResponse->clear(); + ui->responseBuffer->clear(); if(_modbusClient.state() != QModbusDevice::ConnectedState) { - QMessageBox::warning(this, parentWidget()->windowTitle(), "Custom Cmd Write Failure"); + QMessageBox::warning(this, windowTitle(), tr("No connection to device")); return; } @@ -69,7 +69,7 @@ void DialogUserMsg::accept() QModbusRequest request; request.setFunctionCode(ui->lineEditFunction->value()); - request.setData(ui->lineEditSendData->value()); + request.setData(ui->sendData->value()); _modbusClient.sendRawRequest(request, ui->lineEditSlaveAddress->value(), 0); @@ -100,7 +100,7 @@ void DialogUserMsg::on_modbusReply(QModbusReply* reply) const auto response = reply->rawResult(); const auto msg = ModbusMessage::create(response, QDateTime::currentDateTime(), reply->serverAddress(), false); - ui->lineEditResponse->setValue(*msg); + ui->responseBuffer->setValue(*msg); ui->responseInfo->setModbusMessage(msg); ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(true); @@ -118,8 +118,8 @@ void DialogUserMsg::on_radioButtonHex_clicked(bool checked) ui->lineEditSlaveAddress->setInputMode(NumericLineEdit::HexMode); ui->lineEditFunction->setPaddingZeroes(true); ui->lineEditFunction->setInputMode(NumericLineEdit::HexMode); - ui->lineEditSendData->setInputMode(ByteListLineEdit::HexMode); - ui->lineEditResponse->setInputMode(ByteListLineEdit::HexMode); + ui->sendData->setInputMode(ByteListTextEdit::HexMode); + ui->responseBuffer->setInputMode(ByteListTextEdit::HexMode); ui->responseInfo->setDataDisplayMode(DataDisplayMode::Hex); } } @@ -136,8 +136,8 @@ void DialogUserMsg::on_radioButtonDecimal_clicked(bool checked) ui->lineEditSlaveAddress->setInputMode(NumericLineEdit::DecMode); ui->lineEditFunction->setPaddingZeroes(false); ui->lineEditFunction->setInputMode(NumericLineEdit::DecMode); - ui->lineEditSendData->setInputMode(ByteListLineEdit::DecMode); - ui->lineEditResponse->setInputMode(ByteListLineEdit::DecMode); + ui->sendData->setInputMode(ByteListTextEdit::DecMode); + ui->responseBuffer->setInputMode(ByteListTextEdit::DecMode); ui->responseInfo->setDataDisplayMode(DataDisplayMode::Decimal); } } diff --git a/omodscan/dialogs/dialogusermsg.ui b/omodscan/dialogs/dialogusermsg.ui index 58e74fe..2110270 100644 --- a/omodscan/dialogs/dialogusermsg.ui +++ b/omodscan/dialogs/dialogusermsg.ui @@ -6,8 +6,8 @@ 0 0 - 442 - 332 + 574 + 389 @@ -142,11 +142,23 @@
- - - false + + + + 0 + 0 + - + + + 16777215 + 52 + + + + Qt::ImhNone + + true @@ -160,26 +172,44 @@ - - - false - - - true - - - - - - - QAbstractItemView::NoEditTriggers - - - QAbstractItemView::NoSelection - - - true + + + Qt::Vertical + + + + 0 + 1 + + + + false + + + true + + + Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse + + + + + + 0 + 3 + + + + QAbstractItemView::NoEditTriggers + + + QAbstractItemView::NoSelection + + + true + + @@ -206,20 +236,19 @@ QLineEdit
numericlineedit.h
- - ByteListLineEdit - QLineEdit -
bytelistlineedit.h
-
ModbusMessageWidget QListWidget
modbusmessagewidget.h
+ + ByteListTextEdit + QPlainTextEdit +
bytelisttextedit.h
+
lineEditFunction - lineEditSendData radioButtonDecimal radioButtonHex lineEditSlaveAddress diff --git a/omodscan/omodscan.pro b/omodscan/omodscan.pro index 55beb63..35f1aeb 100644 --- a/omodscan/omodscan.pro +++ b/omodscan/omodscan.pro @@ -25,7 +25,7 @@ INCLUDEPATH += controls \ SOURCES += \ controls/booleancombobox.cpp \ - controls/bytelistlineedit.cpp \ + controls/bytelisttextedit.cpp \ controls/byteordercombobox.cpp \ controls/clickablelabel.cpp \ controls/connectioncombobox.cpp \ @@ -85,7 +85,7 @@ HEADERS += \ byteorderutils.h \ connectiondetails.h \ controls/booleancombobox.h \ - controls/bytelistlineedit.h \ + controls/bytelisttextedit.h \ controls/byteordercombobox.h \ controls/clickablelabel.h \ controls/connectioncombobox.h \ From 423767865e9c9ad115e5498f996becf3a7740311 Mon Sep 17 00:00:00 2001 From: sanny32 Date: Wed, 4 Oct 2023 13:28:58 +0300 Subject: [PATCH 33/90] Correct bug to view value in dec mode --- omodscan/controls/bytelisttextedit.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/omodscan/controls/bytelisttextedit.cpp b/omodscan/controls/bytelisttextedit.cpp index cb91ed0..6c7cc3f 100644 --- a/omodscan/controls/bytelisttextedit.cpp +++ b/omodscan/controls/bytelisttextedit.cpp @@ -48,7 +48,7 @@ void ByteListTextEdit::setValue(const QByteArray& value) { case DecMode: { - const auto text = formatByteArray(DataDisplayMode::Hex, value); + const auto text = formatByteArray(DataDisplayMode::Decimal, value); if(text != toPlainText()) setPlainText(formatByteArray(DataDisplayMode::Decimal, value)); } From d83f7aae138a98cc3b30aedc0308a34d461be6f1 Mon Sep 17 00:00:00 2001 From: sanny32 Date: Wed, 4 Oct 2023 13:29:18 +0300 Subject: [PATCH 34/90] Refactoring --- omodscan/controls/byteordercombobox.cpp | 2 +- omodscan/controls/functioncodecombobox.cpp | 29 ++++++++++++++++---- omodscan/controls/functioncodecombobox.h | 9 +++++- omodscan/controls/paritytypecombobox.cpp | 11 ++++++++ omodscan/controls/paritytypecombobox.h | 7 +++++ omodscan/controls/pointtypecombobox.cpp | 2 +- omodscan/controls/simulationmodecombobox.cpp | 3 +- omodscan/formatutils.h | 20 ++++++++++++++ 8 files changed, 73 insertions(+), 10 deletions(-) diff --git a/omodscan/controls/byteordercombobox.cpp b/omodscan/controls/byteordercombobox.cpp index 7918464..e50151d 100644 --- a/omodscan/controls/byteordercombobox.cpp +++ b/omodscan/controls/byteordercombobox.cpp @@ -10,7 +10,7 @@ ByteOrderComboBox::ByteOrderComboBox(QWidget *parent) addItem("Little-Endian", QVariant::fromValue(ByteOrder::LittleEndian)); addItem("Big-Endian", QVariant::fromValue(ByteOrder::BigEndian)); - connect(this, SIGNAL(currentIndexChanged(int)), this, SLOT(on_currentIndexChanged(int))); + connect(this, static_cast(&QComboBox::currentIndexChanged), this, &ByteOrderComboBox::on_currentIndexChanged); } /// diff --git a/omodscan/controls/functioncodecombobox.cpp b/omodscan/controls/functioncodecombobox.cpp index 5c14b25..48d4f1e 100644 --- a/omodscan/controls/functioncodecombobox.cpp +++ b/omodscan/controls/functioncodecombobox.cpp @@ -1,4 +1,5 @@ #include "modbusfunction.h" +#include "formatutils.h" #include "functioncodecombobox.h" /// @@ -6,9 +7,10 @@ /// \param parent /// FunctionCodeComboBox::FunctionCodeComboBox(QWidget *parent) - :QComboBox(parent) + : QComboBox(parent) + ,_dataDisplayMode(DataDisplayMode::Decimal) { - connect(this, SIGNAL(currentIndexChanged(int)), this, SLOT(on_currentIndexChanged(int))); + connect(this, static_cast(&QComboBox::currentIndexChanged), this, &FunctionCodeComboBox::on_currentIndexChanged); } /// @@ -30,15 +32,32 @@ void FunctionCodeComboBox::setCurrentFunctionCode(QModbusPdu::FunctionCode funcC setCurrentIndex(idx); } +/// +/// \brief FunctionCodeComboBox::dataDisplayMode +/// \return +/// +DataDisplayMode FunctionCodeComboBox::dataDisplayMode() const +{ + return _dataDisplayMode; +} + +/// +/// \brief FunctionCodeComboBox::setDataDisplayMode +/// \param mode +/// +void FunctionCodeComboBox::setDataDisplayMode(DataDisplayMode mode) +{ + _dataDisplayMode = mode; +} + /// /// \brief FunctionCodeComboBox::addItem /// \param funcCode /// void FunctionCodeComboBox::addItem(QModbusPdu::FunctionCode funcCode) { - ModbusFunction func(funcCode); - const auto code = QString("%1").arg(QString::number(func, 10), 2, '0'); - QComboBox::addItem(QString("%1: %2").arg(code, func), funcCode); + const auto code = formatFuncCode(_dataDisplayMode, funcCode); + QComboBox::addItem(QString("%1: %2").arg(code, ModbusFunction(funcCode)), funcCode); } /// diff --git a/omodscan/controls/functioncodecombobox.h b/omodscan/controls/functioncodecombobox.h index e29bbde..96d76fc 100644 --- a/omodscan/controls/functioncodecombobox.h +++ b/omodscan/controls/functioncodecombobox.h @@ -3,17 +3,21 @@ #include #include +#include "enums.h" class FunctionCodeComboBox : public QComboBox { Q_OBJECT public: - FunctionCodeComboBox(QWidget *parent = nullptr); + explicit FunctionCodeComboBox(QWidget *parent = nullptr); QModbusPdu::FunctionCode currentFunctionCode() const; void setCurrentFunctionCode(QModbusPdu::FunctionCode funcCode); + DataDisplayMode dataDisplayMode() const; + void setDataDisplayMode(DataDisplayMode mode); + void addItem(QModbusPdu::FunctionCode funcCode); signals: @@ -21,6 +25,9 @@ class FunctionCodeComboBox : public QComboBox private slots: void on_currentIndexChanged(int); + +private: + DataDisplayMode _dataDisplayMode; }; #endif // FUNCTIONCODECOMBOBOX_H diff --git a/omodscan/controls/paritytypecombobox.cpp b/omodscan/controls/paritytypecombobox.cpp index 24e9fb1..20b036b 100644 --- a/omodscan/controls/paritytypecombobox.cpp +++ b/omodscan/controls/paritytypecombobox.cpp @@ -10,6 +10,8 @@ ParityTypeComboBox::ParityTypeComboBox(QWidget* parent) addItem(tr("ODD"), QSerialPort::OddParity); addItem(tr("EVEN"), QSerialPort::EvenParity); addItem(tr("NONE"), QSerialPort::NoParity); + + connect(this, static_cast(&QComboBox::currentIndexChanged), this, &ParityTypeComboBox::on_currentIndexChanged); } /// @@ -30,3 +32,12 @@ void ParityTypeComboBox::setCurrentParity(QSerialPort::Parity parity) const auto idx = findData(parity); setCurrentIndex(idx); } + +/// +/// \brief ParityTypeComboBox::on_currentIndexChanged +/// \param index +/// +void ParityTypeComboBox::on_currentIndexChanged(int index) +{ + emit parityTypeChanged(itemData(index).value()); +} diff --git a/omodscan/controls/paritytypecombobox.h b/omodscan/controls/paritytypecombobox.h index 7cb98de..9953975 100644 --- a/omodscan/controls/paritytypecombobox.h +++ b/omodscan/controls/paritytypecombobox.h @@ -10,11 +10,18 @@ class ParityTypeComboBox : public QComboBox { Q_OBJECT + public: ParityTypeComboBox(QWidget *parent = nullptr); QSerialPort::Parity currentParity() const; void setCurrentParity(QSerialPort::Parity parity); + +signals: + void parityTypeChanged(QSerialPort::Parity parity); + +private slots: + void on_currentIndexChanged(int index); }; #endif // PARITYTYPECOMBOBOX_H diff --git a/omodscan/controls/pointtypecombobox.cpp b/omodscan/controls/pointtypecombobox.cpp index c07e55f..8350404 100644 --- a/omodscan/controls/pointtypecombobox.cpp +++ b/omodscan/controls/pointtypecombobox.cpp @@ -13,7 +13,7 @@ PointTypeComboBox::PointTypeComboBox(QWidget *parent) addItem("03: HOLDING REGISTER", QModbusDataUnit::HoldingRegisters); addItem("04: INPUT REGISTER", QModbusDataUnit::InputRegisters); - connect(this, SIGNAL(currentIndexChanged(int)), this, SLOT(on_currentIndexChanged(int))); + connect(this, static_cast(&QComboBox::currentIndexChanged), this, &PointTypeComboBox::on_currentIndexChanged); } /// diff --git a/omodscan/controls/simulationmodecombobox.cpp b/omodscan/controls/simulationmodecombobox.cpp index 9201f17..7492a2a 100644 --- a/omodscan/controls/simulationmodecombobox.cpp +++ b/omodscan/controls/simulationmodecombobox.cpp @@ -7,8 +7,7 @@ SimulationModeComboBox::SimulationModeComboBox(QWidget *parent) : QComboBox(parent) { - - connect(this, SIGNAL(currentIndexChanged(int)), this, SLOT(on_currentIndexChanged(int))); + connect(this, static_cast(&QComboBox::currentIndexChanged), this, &SimulationModeComboBox::on_currentIndexChanged); } /// diff --git a/omodscan/formatutils.h b/omodscan/formatutils.h index ffcd699..25907e7 100644 --- a/omodscan/formatutils.h +++ b/omodscan/formatutils.h @@ -3,11 +3,31 @@ #include #include +#include #include #include "enums.h" #include "numericutils.h" #include "byteorderutils.h" +/// +/// \brief formatFuncCode +/// \param mode +/// \param c +/// \return +/// +inline QString formatFuncCode(DataDisplayMode mode, QModbusPdu::FunctionCode c) +{ + switch(mode) + { + case DataDisplayMode::Decimal: + case DataDisplayMode::Integer: + return QString("%1").arg(QString::number(c), 2, '0'); + + default: + return QString("%1").arg(QString::number(c, 16).toUpper(), 2, '0'); + } +} + /// /// \brief formatByteValue /// \param mode From fdfe7cd79424deed0ffd96ec186e8db1a9d6be3b Mon Sep 17 00:00:00 2001 From: sanny32 Date: Wed, 4 Oct 2023 16:12:24 +0300 Subject: [PATCH 35/90] Correct comment --- omodscan/controls/numericlineedit.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/omodscan/controls/numericlineedit.cpp b/omodscan/controls/numericlineedit.cpp index 981fbc9..a3ac9a8 100644 --- a/omodscan/controls/numericlineedit.cpp +++ b/omodscan/controls/numericlineedit.cpp @@ -68,7 +68,7 @@ NumericLineEdit::InputMode NumericLineEdit::inputMode() const } /// -/// \brief NumericLineEdit::setHexInput +/// \brief NumericLineEdit::setInputMode /// \param on /// void NumericLineEdit::setInputMode(InputMode mode) From 64d73b13f39b4f19cd354571965d260eeb2e9759 Mon Sep 17 00:00:00 2001 From: sanny32 Date: Wed, 4 Oct 2023 16:59:34 +0300 Subject: [PATCH 36/90] Improve dialog user message behavior --- omodscan/controls/functioncodecombobox.cpp | 124 +++++++++++++++++++-- omodscan/controls/functioncodecombobox.h | 22 +++- omodscan/dialogs/dialogusermsg.cpp | 19 ++-- omodscan/dialogs/dialogusermsg.ui | 28 +++-- 4 files changed, 157 insertions(+), 36 deletions(-) diff --git a/omodscan/controls/functioncodecombobox.cpp b/omodscan/controls/functioncodecombobox.cpp index 48d4f1e..8ece993 100644 --- a/omodscan/controls/functioncodecombobox.cpp +++ b/omodscan/controls/functioncodecombobox.cpp @@ -1,5 +1,9 @@ +#include #include "modbusfunction.h" +#include "enums.h" #include "formatutils.h" +#include "qhexvalidator.h" +#include "quintvalidator.h" #include "functioncodecombobox.h" /// @@ -8,8 +12,11 @@ /// FunctionCodeComboBox::FunctionCodeComboBox(QWidget *parent) : QComboBox(parent) - ,_dataDisplayMode(DataDisplayMode::Decimal) + ,_currentFunc(QModbusPdu::Invalid) { + setInputMode(InputMode::DecMode); + + connect(this, &QComboBox::currentTextChanged, this, &FunctionCodeComboBox::on_currentTextChanged); connect(this, static_cast(&QComboBox::currentIndexChanged), this, &FunctionCodeComboBox::on_currentIndexChanged); } @@ -19,7 +26,7 @@ FunctionCodeComboBox::FunctionCodeComboBox(QWidget *parent) /// QModbusPdu::FunctionCode FunctionCodeComboBox::currentFunctionCode() const { - return currentData().value(); + return _currentFunc; } /// @@ -28,26 +35,42 @@ QModbusPdu::FunctionCode FunctionCodeComboBox::currentFunctionCode() const /// void FunctionCodeComboBox::setCurrentFunctionCode(QModbusPdu::FunctionCode funcCode) { + _currentFunc = funcCode; + const auto mode = (_inputMode == InputMode::HexMode) ? DataDisplayMode::Hex : DataDisplayMode::Decimal; const auto idx = findData(funcCode); - setCurrentIndex(idx); + if(idx != -1) setCurrentIndex(idx); + else setCurrentText(formatFuncCode(mode, funcCode)); } /// -/// \brief FunctionCodeComboBox::dataDisplayMode +/// \brief FunctionCodeComboBox::inputMode /// \return /// -DataDisplayMode FunctionCodeComboBox::dataDisplayMode() const +FunctionCodeComboBox::InputMode FunctionCodeComboBox::inputMode() const { - return _dataDisplayMode; + return _inputMode; } /// -/// \brief FunctionCodeComboBox::setDataDisplayMode -/// \param mode +/// \brief FunctionCodeComboBox::setInputMode +/// \param on /// -void FunctionCodeComboBox::setDataDisplayMode(DataDisplayMode mode) +void FunctionCodeComboBox::setInputMode(FunctionCodeComboBox::InputMode mode) { - _dataDisplayMode = mode; + _inputMode = mode; + + switch(mode) + { + case DecMode: + // setValidator(new QUIntValidator(0, 255, this)); + break; + + case HexMode: + // setValidator(new QHexValidator(0, 0xFF, this)); + break; + } + + update(); } /// @@ -56,15 +79,92 @@ void FunctionCodeComboBox::setDataDisplayMode(DataDisplayMode mode) /// void FunctionCodeComboBox::addItem(QModbusPdu::FunctionCode funcCode) { - const auto code = formatFuncCode(_dataDisplayMode, funcCode); + const auto mode = (_inputMode == InputMode::HexMode) ? DataDisplayMode::Hex : DataDisplayMode::Decimal; + const auto code = formatFuncCode(mode, funcCode); QComboBox::addItem(QString("%1: %2").arg(code, ModbusFunction(funcCode)), funcCode); } +/// +/// \brief FunctionCodeComboBox::addAllItems +/// +void FunctionCodeComboBox::addAllItems() +{ + static const auto items = { + QModbusPdu::ReadCoils, QModbusPdu::ReadDiscreteInputs, QModbusPdu::ReadHoldingRegisters, QModbusPdu::ReadInputRegisters, + QModbusPdu::WriteSingleCoil, QModbusPdu::WriteSingleRegister, QModbusPdu::ReadExceptionStatus, QModbusPdu::Diagnostics, + QModbusPdu::GetCommEventCounter, QModbusPdu::GetCommEventLog, QModbusPdu::WriteMultipleCoils, QModbusPdu::WriteMultipleRegisters, + QModbusPdu::ReportServerId, QModbusPdu::ReadFileRecord, QModbusPdu::WriteFileRecord, QModbusPdu::MaskWriteRegister, + QModbusPdu::ReadWriteMultipleRegisters, QModbusPdu::ReadFifoQueue, QModbusPdu::EncapsulatedInterfaceTransport + }; + + for(auto&& item : items) + addItem(item); +} + +/// +/// \brief FunctionCodeComboBox::update +/// +void FunctionCodeComboBox::update() +{ + const auto mode = (_inputMode == InputMode::HexMode) ? DataDisplayMode::Hex : DataDisplayMode::Decimal; + + if(currentData(Qt::DisplayRole) != currentText()) + { + const auto code = formatFuncCode(mode, currentFunctionCode()); + setCurrentText(code); + } + + for (int i = 0; i < count(); i++) + { + const auto funcCode = itemData(i).value(); + const auto code = formatFuncCode(mode, funcCode); + setItemText(i, QString("%1: %2").arg(code, ModbusFunction(funcCode))); + } +} + /// /// \brief FunctionCodeComboBox::on_currentIndexChanged /// \param index /// void FunctionCodeComboBox::on_currentIndexChanged(int index) { - emit functionCodeChanged(itemData(index).value()); + _currentFunc = itemData(index).value(); + emit functionCodeChanged(_currentFunc); +} + +/// +/// \brief FunctionCodeComboBox::on_currentTextChanged +/// +void FunctionCodeComboBox::on_currentTextChanged(const QString& text) +{ + if(currentData(Qt::DisplayRole) == text) + _currentFunc = currentData().value(); + else + { + bool ok; + quint8 func; + + switch(_inputMode) + { + case InputMode::DecMode: + func = text.toUInt(&ok); + break; + + case InputMode::HexMode: + func = text.toUInt(&ok, 16); + break; + } + + _currentFunc = ok ? (QModbusPdu::FunctionCode)func : QModbusPdu::Invalid; + } +} + +/// +/// \brief FunctionCodeComboBox::focusOutEvent +/// \param e +/// +void FunctionCodeComboBox::focusOutEvent(QFocusEvent* e) +{ + update(); + QComboBox::focusOutEvent(e); } diff --git a/omodscan/controls/functioncodecombobox.h b/omodscan/controls/functioncodecombobox.h index 96d76fc..0f6032c 100644 --- a/omodscan/controls/functioncodecombobox.h +++ b/omodscan/controls/functioncodecombobox.h @@ -3,31 +3,45 @@ #include #include -#include "enums.h" class FunctionCodeComboBox : public QComboBox { Q_OBJECT public: + enum InputMode + { + DecMode = 0, + HexMode + }; + explicit FunctionCodeComboBox(QWidget *parent = nullptr); QModbusPdu::FunctionCode currentFunctionCode() const; void setCurrentFunctionCode(QModbusPdu::FunctionCode funcCode); - DataDisplayMode dataDisplayMode() const; - void setDataDisplayMode(DataDisplayMode mode); + InputMode inputMode() const; + void setInputMode(InputMode mode); void addItem(QModbusPdu::FunctionCode funcCode); + void addAllItems(); signals: void functionCodeChanged(QModbusPdu::FunctionCode funcCode); +protected: + void focusOutEvent(QFocusEvent* e) override; + private slots: void on_currentIndexChanged(int); + void on_currentTextChanged(const QString&); + +private: + void update(); private: - DataDisplayMode _dataDisplayMode; + InputMode _inputMode; + QModbusPdu::FunctionCode _currentFunc; }; #endif // FUNCTIONCODECOMBOBOX_H diff --git a/omodscan/dialogs/dialogusermsg.cpp b/omodscan/dialogs/dialogusermsg.cpp index e671a14..1395d8b 100644 --- a/omodscan/dialogs/dialogusermsg.cpp +++ b/omodscan/dialogs/dialogusermsg.cpp @@ -22,10 +22,14 @@ DialogUserMsg::DialogUserMsg(quint8 slaveAddress, QModbusPdu::FunctionCode func, { ui->setupUi(this); + setWindowFlags(Qt::Dialog | + Qt::CustomizeWindowHint | + Qt::WindowTitleHint); + ui->lineEditSlaveAddress->setInputRange(ModbusLimits::slaveRange()); ui->lineEditSlaveAddress->setValue(slaveAddress); - ui->lineEditFunction->setInputRange(0, 255); - ui->lineEditFunction->setValue(func); + ui->comboBoxFunction->addAllItems(); + ui->comboBoxFunction->setCurrentFunctionCode(func); ui->responseInfo->setShowTimestamp(false); switch(mode) @@ -39,7 +43,8 @@ DialogUserMsg::DialogUserMsg(quint8 slaveAddress, QModbusPdu::FunctionCode func, break; } - ui->buttonBox->button(QDialogButtonBox::Ok)->setText("Send"); + ui->buttonBox->button(QDialogButtonBox::Ok)->setText(tr("Send")); + ui->sendData->setFocus(); connect(&_modbusClient, &ModbusClient::modbusReply, this, &DialogUserMsg::on_modbusReply); } @@ -68,7 +73,7 @@ void DialogUserMsg::accept() ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false); QModbusRequest request; - request.setFunctionCode(ui->lineEditFunction->value()); + request.setFunctionCode(ui->comboBoxFunction->currentFunctionCode()); request.setData(ui->sendData->value()); _modbusClient.sendRawRequest(request, ui->lineEditSlaveAddress->value(), 0); @@ -116,8 +121,7 @@ void DialogUserMsg::on_radioButtonHex_clicked(bool checked) { ui->lineEditSlaveAddress->setPaddingZeroes(true); ui->lineEditSlaveAddress->setInputMode(NumericLineEdit::HexMode); - ui->lineEditFunction->setPaddingZeroes(true); - ui->lineEditFunction->setInputMode(NumericLineEdit::HexMode); + ui->comboBoxFunction->setInputMode(FunctionCodeComboBox::HexMode); ui->sendData->setInputMode(ByteListTextEdit::HexMode); ui->responseBuffer->setInputMode(ByteListTextEdit::HexMode); ui->responseInfo->setDataDisplayMode(DataDisplayMode::Hex); @@ -134,8 +138,7 @@ void DialogUserMsg::on_radioButtonDecimal_clicked(bool checked) { ui->lineEditSlaveAddress->setPaddingZeroes(false); ui->lineEditSlaveAddress->setInputMode(NumericLineEdit::DecMode); - ui->lineEditFunction->setPaddingZeroes(false); - ui->lineEditFunction->setInputMode(NumericLineEdit::DecMode); + ui->comboBoxFunction->setInputMode(FunctionCodeComboBox::DecMode); ui->sendData->setInputMode(ByteListTextEdit::DecMode); ui->responseBuffer->setInputMode(ByteListTextEdit::DecMode); ui->responseInfo->setDataDisplayMode(DataDisplayMode::Decimal); diff --git a/omodscan/dialogs/dialogusermsg.ui b/omodscan/dialogs/dialogusermsg.ui index 2110270..1e53247 100644 --- a/omodscan/dialogs/dialogusermsg.ui +++ b/omodscan/dialogs/dialogusermsg.ui @@ -42,6 +42,9 @@ 16777215 + + Qt::NoContextMenu +
@@ -52,18 +55,12 @@
- - - - 0 - 0 - + + + Qt::NoContextMenu - - - 40 - 16777215 - + + true @@ -161,6 +158,9 @@ true + + Enter bytes value separated by spaces +
@@ -246,9 +246,13 @@ QPlainTextEdit
bytelisttextedit.h
+ + FunctionCodeComboBox + QComboBox +
functioncodecombobox.h
+
- lineEditFunction radioButtonDecimal radioButtonHex lineEditSlaveAddress From c6c0105903357ceb121650b2be902e2d57fc2b2f Mon Sep 17 00:00:00 2001 From: sanny32 Date: Wed, 4 Oct 2023 17:08:55 +0300 Subject: [PATCH 37/90] Refactoring --- omodscan/controls/functioncodecombobox.cpp | 24 ++++++++++++++-------- omodscan/controls/functioncodecombobox.h | 1 + 2 files changed, 17 insertions(+), 8 deletions(-) diff --git a/omodscan/controls/functioncodecombobox.cpp b/omodscan/controls/functioncodecombobox.cpp index 8ece993..8ef1c6d 100644 --- a/omodscan/controls/functioncodecombobox.cpp +++ b/omodscan/controls/functioncodecombobox.cpp @@ -36,10 +36,10 @@ QModbusPdu::FunctionCode FunctionCodeComboBox::currentFunctionCode() const void FunctionCodeComboBox::setCurrentFunctionCode(QModbusPdu::FunctionCode funcCode) { _currentFunc = funcCode; - const auto mode = (_inputMode == InputMode::HexMode) ? DataDisplayMode::Hex : DataDisplayMode::Decimal; + const auto idx = findData(funcCode); if(idx != -1) setCurrentIndex(idx); - else setCurrentText(formatFuncCode(mode, funcCode)); + else setCurrentText(formatFuncCode(funcCode)); } /// @@ -79,8 +79,7 @@ void FunctionCodeComboBox::setInputMode(FunctionCodeComboBox::InputMode mode) /// void FunctionCodeComboBox::addItem(QModbusPdu::FunctionCode funcCode) { - const auto mode = (_inputMode == InputMode::HexMode) ? DataDisplayMode::Hex : DataDisplayMode::Decimal; - const auto code = formatFuncCode(mode, funcCode); + const auto code = formatFuncCode(funcCode); QComboBox::addItem(QString("%1: %2").arg(code, ModbusFunction(funcCode)), funcCode); } @@ -106,22 +105,31 @@ void FunctionCodeComboBox::addAllItems() /// void FunctionCodeComboBox::update() { - const auto mode = (_inputMode == InputMode::HexMode) ? DataDisplayMode::Hex : DataDisplayMode::Decimal; - if(currentData(Qt::DisplayRole) != currentText()) { - const auto code = formatFuncCode(mode, currentFunctionCode()); + const auto code = formatFuncCode(currentFunctionCode()); setCurrentText(code); } for (int i = 0; i < count(); i++) { const auto funcCode = itemData(i).value(); - const auto code = formatFuncCode(mode, funcCode); + const auto code = formatFuncCode( funcCode); setItemText(i, QString("%1: %2").arg(code, ModbusFunction(funcCode))); } } +/// +/// \brief FunctionCodeComboBox::formatFuncCode +/// \param funcCode +/// \return +/// +QString FunctionCodeComboBox::formatFuncCode(QModbusPdu::FunctionCode funcCode) const +{ + const auto mode = (_inputMode == InputMode::HexMode) ? DataDisplayMode::Hex : DataDisplayMode::Decimal; + return ::formatFuncCode(mode, funcCode); +} + /// /// \brief FunctionCodeComboBox::on_currentIndexChanged /// \param index diff --git a/omodscan/controls/functioncodecombobox.h b/omodscan/controls/functioncodecombobox.h index 0f6032c..27c7933 100644 --- a/omodscan/controls/functioncodecombobox.h +++ b/omodscan/controls/functioncodecombobox.h @@ -38,6 +38,7 @@ private slots: private: void update(); + QString formatFuncCode(QModbusPdu::FunctionCode funcCode) const; private: InputMode _inputMode; From 374f756c4180c2761afc21de9638802ac459a8fb Mon Sep 17 00:00:00 2001 From: sanny32 Date: Thu, 5 Oct 2023 08:55:19 +0300 Subject: [PATCH 38/90] Correct bug when _validator field is nullptr --- omodscan/controls/bytelisttextedit.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/omodscan/controls/bytelisttextedit.cpp b/omodscan/controls/bytelisttextedit.cpp index 6c7cc3f..b2d8e32 100644 --- a/omodscan/controls/bytelisttextedit.cpp +++ b/omodscan/controls/bytelisttextedit.cpp @@ -143,6 +143,12 @@ void ByteListTextEdit::focusOutEvent(QFocusEvent* e) /// void ByteListTextEdit::keyPressEvent(QKeyEvent *e) { + if(!_validator) + { + QPlainTextEdit::keyPressEvent(e); + return; + } + int pos = 0; auto text = toPlainText() + e->text(); const auto state = _validator->validate(text, pos); From 59147b7cf3518774d7e5899acf3cebd55b1ffc64 Mon Sep 17 00:00:00 2001 From: sanny32 Date: Thu, 5 Oct 2023 09:16:09 +0300 Subject: [PATCH 39/90] Correct text input into combobox --- omodscan/controls/functioncodecombobox.cpp | 57 +++++++++++++++++++--- omodscan/controls/functioncodecombobox.h | 2 + 2 files changed, 53 insertions(+), 6 deletions(-) diff --git a/omodscan/controls/functioncodecombobox.cpp b/omodscan/controls/functioncodecombobox.cpp index 8ef1c6d..1184054 100644 --- a/omodscan/controls/functioncodecombobox.cpp +++ b/omodscan/controls/functioncodecombobox.cpp @@ -1,4 +1,5 @@ #include +#include #include "modbusfunction.h" #include "enums.h" #include "formatutils.h" @@ -13,6 +14,7 @@ FunctionCodeComboBox::FunctionCodeComboBox(QWidget *parent) : QComboBox(parent) ,_currentFunc(QModbusPdu::Invalid) + ,_validator(nullptr) { setInputMode(InputMode::DecMode); @@ -57,16 +59,25 @@ FunctionCodeComboBox::InputMode FunctionCodeComboBox::inputMode() const /// void FunctionCodeComboBox::setInputMode(FunctionCodeComboBox::InputMode mode) { + if(!isEditable()) + return; + _inputMode = mode; + if(_validator) + { + delete _validator; + _validator = nullptr; + } + switch(mode) { case DecMode: - // setValidator(new QUIntValidator(0, 255, this)); + _validator = new QUIntValidator(0, 255, this); break; case HexMode: - // setValidator(new QHexValidator(0, 0xFF, this)); + _validator = new QHexValidator(0, 0xFF, this); break; } @@ -107,8 +118,9 @@ void FunctionCodeComboBox::update() { if(currentData(Qt::DisplayRole) != currentText()) { - const auto code = formatFuncCode(currentFunctionCode()); - setCurrentText(code); + const auto idx = findData(_currentFunc); + if(idx != -1) setCurrentIndex(idx); + else setCurrentText(formatFuncCode(_currentFunc)); } for (int i = 0; i < count(); i++) @@ -145,8 +157,11 @@ void FunctionCodeComboBox::on_currentIndexChanged(int index) /// void FunctionCodeComboBox::on_currentTextChanged(const QString& text) { - if(currentData(Qt::DisplayRole) == text) - _currentFunc = currentData().value(); + const auto idx = findData(text, Qt::DisplayRole); + if(idx != -1) + { + _currentFunc = itemData(idx).value(); + } else { bool ok; @@ -176,3 +191,33 @@ void FunctionCodeComboBox::focusOutEvent(QFocusEvent* e) update(); QComboBox::focusOutEvent(e); } + +/// +/// \brief FunctionCodeComboBox::keyPressEvent +/// \param e +/// +void FunctionCodeComboBox::keyPressEvent(QKeyEvent* e) +{ + if(!_validator || !isEditable()) + { + QComboBox::keyPressEvent(e); + return; + } + + int pos = 0; + auto text = e->text(); + const auto state = _validator->validate(text, pos); + + if(state == QValidator::Acceptable || + e->key() == Qt::Key_Backspace || + e->key() == Qt::Key_Delete || + e->matches(QKeySequence::Cut) || + e->matches(QKeySequence::Copy) || + e->matches(QKeySequence::Paste) || + e->matches(QKeySequence::Undo) || + e->matches(QKeySequence::Redo) || + e->matches(QKeySequence::SelectAll)) + { + QComboBox::keyPressEvent(e); + } +} diff --git a/omodscan/controls/functioncodecombobox.h b/omodscan/controls/functioncodecombobox.h index 27c7933..3786612 100644 --- a/omodscan/controls/functioncodecombobox.h +++ b/omodscan/controls/functioncodecombobox.h @@ -31,6 +31,7 @@ class FunctionCodeComboBox : public QComboBox protected: void focusOutEvent(QFocusEvent* e) override; + void keyPressEvent(QKeyEvent* e) override; private slots: void on_currentIndexChanged(int); @@ -43,6 +44,7 @@ private slots: private: InputMode _inputMode; QModbusPdu::FunctionCode _currentFunc; + QValidator* _validator; }; #endif // FUNCTIONCODECOMBOBOX_H From fa048f8f96c09c898a82d206fc4fc436c05f6289 Mon Sep 17 00:00:00 2001 From: sanny32 Date: Thu, 5 Oct 2023 09:50:36 +0300 Subject: [PATCH 40/90] Capture text functionality changed to capture modbus log --- omodscan/controls/modbuslogwidget.cpp | 19 +++++++++++++++++ omodscan/controls/modbuslogwidget.h | 4 ++++ omodscan/controls/outputwidget.cpp | 30 ++++++++++++++------------- 3 files changed, 39 insertions(+), 14 deletions(-) diff --git a/omodscan/controls/modbuslogwidget.cpp b/omodscan/controls/modbuslogwidget.cpp index 36d2d57..3d6b251 100644 --- a/omodscan/controls/modbuslogwidget.cpp +++ b/omodscan/controls/modbuslogwidget.cpp @@ -138,6 +138,25 @@ void ModbusLogWidget::clear() ((ModbusLogModel*)model())->clear(); } +/// +/// \brief ModbusLogWidget::rowCount +/// \return +/// +int ModbusLogWidget::rowCount() const +{ + return model()->rowCount(); +} + +/// +/// \brief ModbusLogWidget::index +/// \param row +/// \return +/// +QModelIndex ModbusLogWidget::index(int row) +{ + return model()->index(row, 0); +} + /// /// \brief ModbusLogWidget::addItem /// \param pdu diff --git a/omodscan/controls/modbuslogwidget.h b/omodscan/controls/modbuslogwidget.h index 637591a..aa5f11f 100644 --- a/omodscan/controls/modbuslogwidget.h +++ b/omodscan/controls/modbuslogwidget.h @@ -49,6 +49,10 @@ class ModbusLogWidget : public QListView explicit ModbusLogWidget(QWidget* parent = nullptr); void clear(); + + int rowCount() const; + QModelIndex index(int row); + void addItem(const QModbusPdu& pdu, const QDateTime& timestamp, int deviceId, bool request); const ModbusMessage* itemAt(const QModelIndex& index); diff --git a/omodscan/controls/outputwidget.cpp b/omodscan/controls/outputwidget.cpp index 4812be6..a84abd7 100644 --- a/omodscan/controls/outputwidget.cpp +++ b/omodscan/controls/outputwidget.cpp @@ -533,10 +533,7 @@ void OutputWidget::setStatus(const QString& status) { const auto info = QString("** %1 **").arg(status); if(info != ui->labelStatus->text()) - { ui->labelStatus->setText(info); - captureString(info); - } } } @@ -608,14 +605,6 @@ void OutputWidget::updateTraffic(const QModbusResponse& response, int deviceId) void OutputWidget::updateData(const QModbusDataUnit& data) { _listModel->updateData(data); - - if(captureMode() == CaptureMode::TextCapture) - { - QStringList capstr; - for(int i = 0; i < _listModel->rowCount(); i++) - capstr.push_back(_listModel->data(_listModel->index(i), CaptureRole).toString()); - captureString(capstr.join(' ')); - } } /// @@ -809,9 +798,7 @@ void OutputWidget::captureString(const QString& s) if(_fileCapture.isOpen()) { QTextStream stream(&_fileCapture); - stream << QDateTime::currentDateTime().toString(Qt::ISODateWithMs) << " " << - formatAddress(_displayDefinition.PointType, _displayDefinition.PointAddress, false) << " " - << s << "\n"; + stream << s << "\n"; } } @@ -833,4 +820,19 @@ void OutputWidget::showModbusMessage(const QModelIndex& index) void OutputWidget::updateLogView(bool request, int server, const QModbusPdu& pdu) { ui->logView->addItem(pdu, QDateTime::currentDateTime(), server, request); + + if(captureMode() == CaptureMode::TextCapture) + { + const auto idx = ui->logView->index(ui->logView->rowCount() - 1); + const auto msg = ui->logView->itemAt(idx); + + if(msg != nullptr) + { + const auto str = QString("%1 %2 %3").arg( + msg->timestamp().toString(Qt::ISODateWithMs), + (msg->isRequest()? "<<" : ">>"), + msg->toString(DataDisplayMode::Hex)); + captureString(str); + } + } } From 03394742283265195bba696ec43f53df802ecf3b Mon Sep 17 00:00:00 2001 From: sanny32 Date: Thu, 5 Oct 2023 10:43:37 +0300 Subject: [PATCH 41/90] Fix access violation possible bug --- omodscan/controls/modbuslogwidget.cpp | 44 +++++++++++++++++++++------ omodscan/controls/modbuslogwidget.h | 4 +++ 2 files changed, 39 insertions(+), 9 deletions(-) diff --git a/omodscan/controls/modbuslogwidget.cpp b/omodscan/controls/modbuslogwidget.cpp index 3d6b251..f1c771c 100644 --- a/omodscan/controls/modbuslogwidget.cpp +++ b/omodscan/controls/modbuslogwidget.cpp @@ -119,13 +119,14 @@ void ModbusLogModel::deleteItems() /// ModbusLogWidget::ModbusLogWidget(QWidget* parent) : QListView(parent) + , _autoscroll(false) { setItemDelegate(new HtmlDelegate(this)); setModel(new ModbusLogModel(this)); connect(model(), &ModbusLogModel::rowsInserted, this, [&]{ - //scrollToBottom(); + if(_autoscroll) scrollToBottom(); setCurrentIndex(QModelIndex()); }); } @@ -135,7 +136,8 @@ ModbusLogWidget::ModbusLogWidget(QWidget* parent) /// void ModbusLogWidget::clear() { - ((ModbusLogModel*)model())->clear(); + if(model()) + ((ModbusLogModel*)model())->clear(); } /// @@ -144,7 +146,7 @@ void ModbusLogWidget::clear() /// int ModbusLogWidget::rowCount() const { - return model()->rowCount(); + return model() ? model()->rowCount() : 0; } /// @@ -154,7 +156,7 @@ int ModbusLogWidget::rowCount() const /// QModelIndex ModbusLogWidget::index(int row) { - return model()->index(row, 0); + return model() ? model()->index(row, 0) : QModelIndex(); } /// @@ -166,7 +168,8 @@ QModelIndex ModbusLogWidget::index(int row) /// void ModbusLogWidget::addItem(const QModbusPdu& pdu, const QDateTime& timestamp, int deviceId, bool request) { - ((ModbusLogModel*)model())->append(ModbusMessage::create(pdu, timestamp, deviceId, request)); + if(model()) + ((ModbusLogModel*)model())->append(ModbusMessage::create(pdu, timestamp, deviceId, request)); } /// @@ -179,7 +182,9 @@ const ModbusMessage* ModbusLogWidget::itemAt(const QModelIndex& index) if(!index.isValid()) return nullptr; - return model()->data(index, Qt::UserRole).value(); + return model() ? + model()->data(index, Qt::UserRole).value() : + nullptr; } /// @@ -198,7 +203,9 @@ DataDisplayMode ModbusLogWidget::dataDisplayMode() const void ModbusLogWidget::setDataDisplayMode(DataDisplayMode mode) { _dataDisplayMode = mode; - ((ModbusLogModel*)model())->update(); + + if(model()) + ((ModbusLogModel*)model())->update(); } /// @@ -207,7 +214,7 @@ void ModbusLogWidget::setDataDisplayMode(DataDisplayMode mode) /// int ModbusLogWidget::rowLimit() const { - return ((ModbusLogModel*)model())->rowLimit(); + return model() ? ((ModbusLogModel*)model())->rowLimit() : 0; } /// @@ -216,5 +223,24 @@ int ModbusLogWidget::rowLimit() const /// void ModbusLogWidget::setRowLimit(int val) { - ((ModbusLogModel*)model())->setRowLimit(val); + if(model()) + ((ModbusLogModel*)model())->setRowLimit(val); +} + +/// +/// \brief ModbusLogWidget::autoscroll +/// \return +/// +bool ModbusLogWidget::autoscroll() const +{ + return _autoscroll; +} + +/// +/// \brief ModbusLogWidget::setAutoscroll +/// \param on +/// +void ModbusLogWidget::setAutoscroll(bool on) +{ + _autoscroll = on; } diff --git a/omodscan/controls/modbuslogwidget.h b/omodscan/controls/modbuslogwidget.h index aa5f11f..2b8f9e9 100644 --- a/omodscan/controls/modbuslogwidget.h +++ b/omodscan/controls/modbuslogwidget.h @@ -62,7 +62,11 @@ class ModbusLogWidget : public QListView int rowLimit() const; void setRowLimit(int val); + bool autoscroll() const; + void setAutoscroll(bool on); + private: + bool _autoscroll; DataDisplayMode _dataDisplayMode; }; From 3d56e7078c131f04f900b6cda60920d9bad3e16c Mon Sep 17 00:00:00 2001 From: sanny32 Date: Thu, 5 Oct 2023 10:58:14 +0300 Subject: [PATCH 42/90] Remove focus from ModbusMessageWidget --- omodscan/controls/outputwidget.ui | 3 +++ 1 file changed, 3 insertions(+) diff --git a/omodscan/controls/outputwidget.ui b/omodscan/controls/outputwidget.ui index a003891..7327d3f 100644 --- a/omodscan/controls/outputwidget.ui +++ b/omodscan/controls/outputwidget.ui @@ -170,6 +170,9 @@ 1 + + Qt::NoFocus + QAbstractItemView::NoEditTriggers From 47ed026c46a618af42678c8c26f93d6634196de3 Mon Sep 17 00:00:00 2001 From: sanny32 Date: Thu, 5 Oct 2023 11:09:04 +0300 Subject: [PATCH 43/90] Refactoring --- omodscan/modbusclient.cpp | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/omodscan/modbusclient.cpp b/omodscan/modbusclient.cpp index 35f4376..bb8736c 100644 --- a/omodscan/modbusclient.cpp +++ b/omodscan/modbusclient.cpp @@ -1,15 +1,16 @@ #include -#include "numericutils.h" -#include "modbusexception.h" -#include "modbusclient.h" #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) - #include - typedef QModbusRtuSerialMaster QModbusRtuSerialClient; +#include +typedef QModbusRtuSerialMaster QModbusRtuSerialClient; #else - #include +#include #endif +#include "formatutils.h" +#include "numericutils.h" +#include "modbusexception.h" +#include "modbusclient.h" /// /// \brief ModbusClient::ModbusClient @@ -621,7 +622,7 @@ void ModbusClient::on_writeReply() if (reply->error() == QModbusDevice::ProtocolError) { ModbusException ex(raw.exceptionCode()); - emit modbusError(QString("%1. %2 (0x%3)").arg(errorDesc, ex, QString::number(ex, 16)), requestId); + emit modbusError(QString("%1. %2 (0x%3)").arg(errorDesc, ex, formatByteValue(DataDisplayMode::Hex, ex)), requestId); } else if(reply->error() != QModbusDevice::NoError) emit modbusError(QString("%1. %2").arg(errorDesc, reply->errorString()), requestId); From eb88ce9e49c072b1a249ea9b4b229dc627e9f96a Mon Sep 17 00:00:00 2001 From: sanny32 Date: Thu, 5 Oct 2023 11:54:03 +0300 Subject: [PATCH 44/90] Correct some bugs in modbus reply processing --- omodscan/formmodsca.cpp | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/omodscan/formmodsca.cpp b/omodscan/formmodsca.cpp index 8dfbbc0..be511ce 100644 --- a/omodscan/formmodsca.cpp +++ b/omodscan/formmodsca.cpp @@ -534,20 +534,18 @@ bool FormModSca::isValidReply(const QModbusReply* reply) const switch(response.functionCode()) { - case QModbusRequest::ReadCoils: - case QModbusRequest::ReadDiscreteInputs: + case QModbusPdu::ReadCoils: + case QModbusPdu::ReadDiscreteInputs: return (data.startAddress() == dd.PointAddress - 1) && (data.valueCount() - dd.Length) < 8; break; - case QModbusRequest::ReadInputRegisters: - case QModbusRequest::ReadHoldingRegisters: + case QModbusPdu::ReadInputRegisters: + case QModbusPdu::ReadHoldingRegisters: return (data.valueCount() == dd.Length) && (data.startAddress() == dd.PointAddress - 1); default: - break; + return true; } - - return false; } /// @@ -635,7 +633,7 @@ void FormModSca::on_modbusReply(QModbusReply* reply) default: if(!hasError) beginUpdate(); - break; + return; } if(reply->property("RequestId").toInt() != _formId) From d8608a80db74df0f12ccc9760ec6925d415ddef8 Mon Sep 17 00:00:00 2001 From: sanny32 Date: Thu, 5 Oct 2023 14:51:49 +0300 Subject: [PATCH 45/90] Fixed access violation at close window --- omodscan/formmodsca.cpp | 8 ++++---- omodscan/formmodsca.h | 4 ++-- omodscan/mainwindow.h | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/omodscan/formmodsca.cpp b/omodscan/formmodsca.cpp index be511ce..e1f7b0a 100644 --- a/omodscan/formmodsca.cpp +++ b/omodscan/formmodsca.cpp @@ -19,7 +19,7 @@ QVersionNumber FormModSca::VERSION = QVersionNumber(1, 4); /// \param ver /// \param parent /// -FormModSca::FormModSca(int id, ModbusClient& client, QSharedPointer simulator, MainWindow* parent) +FormModSca::FormModSca(int id, ModbusClient& client, DataSimulator* simulator, MainWindow* parent) : QWidget(parent) , ui(new Ui::FormModSca) ,_formId(id) @@ -56,9 +56,9 @@ FormModSca::FormModSca(int id, ModbusClient& client, QSharedPointer simulator, MainWindow* parent); + explicit FormModSca(int id, ModbusClient& client, DataSimulator* simulator, MainWindow* parent); ~FormModSca(); int formId() const { @@ -134,7 +134,7 @@ private slots: QTimer _timer; QString _filename; ModbusClient& _modbusClient; - QSharedPointer _dataSimulator; + DataSimulator* _dataSimulator; }; /// diff --git a/omodscan/mainwindow.h b/omodscan/mainwindow.h index b87f990..86dafb7 100644 --- a/omodscan/mainwindow.h +++ b/omodscan/mainwindow.h @@ -149,6 +149,6 @@ private slots: WindowActionList* _windowActionList; RecentFileActionList* _recentFileActionList; QSharedPointer _selectedPrinter; - QSharedPointer _dataSimulator; + DataSimulator* _dataSimulator; }; #endif // MAINWINDOW_H From 1a1c6c648fcd26297a2a247b028869498ff38415 Mon Sep 17 00:00:00 2001 From: sanny32 Date: Thu, 5 Oct 2023 14:52:41 +0300 Subject: [PATCH 46/90] Reimplement display hex values --- omodscan/controls/numericlineedit.cpp | 36 +++- omodscan/controls/numericlineedit.h | 2 + omodscan/dialogs/dialogusermsg.cpp | 4 - omodscan/formatutils.h | 268 +++++++++++++------------- omodscan/qhexvalidator.cpp | 6 + 5 files changed, 167 insertions(+), 149 deletions(-) diff --git a/omodscan/controls/numericlineedit.cpp b/omodscan/controls/numericlineedit.cpp index a3ac9a8..6785ef1 100644 --- a/omodscan/controls/numericlineedit.cpp +++ b/omodscan/controls/numericlineedit.cpp @@ -1,4 +1,4 @@ -#include +#include #include #include #include "qhexvalidator.h" @@ -154,19 +154,22 @@ void NumericLineEdit::internalSetValue(QVariant value) break; case HexMode: + { value = qBound(_minValue.toInt() > 0 ? _minValue.toUInt() : 0, value.toUInt(), _maxValue.toUInt()); + const QString prefix = (hasFocus() ? "" : "0x"); if(_paddingZeroes) { - const auto text = QStringLiteral("%1").arg(value.toUInt(), _paddingZeroWidth, 16, QLatin1Char('0')).toUpper(); + const auto text = prefix + QStringLiteral("%1").arg(value.toUInt(), _paddingZeroWidth, 16, QLatin1Char('0')).toUpper(); if(text != QLineEdit::text()) QLineEdit::setText(text); } else { - const auto text = QString("%1").arg(value.toUInt(), -1, 16).toUpper(); + const auto text = prefix + QString("%1").arg(value.toUInt(), -1, 16).toUpper(); if(text != QLineEdit::text()) QLineEdit::setText(text); } + } break; case FloatMode: @@ -249,14 +252,33 @@ void NumericLineEdit::updateValue() } } +/// +/// \brief NumericLineEdit::focusInEvent +/// \param e +/// +void NumericLineEdit::focusInEvent(QFocusEvent* e) +{ + updateValue(); + QLineEdit::focusInEvent(e); +} + /// /// \brief NumberLineEdit::focusOutEvent -/// \param event +/// \param e /// -void NumericLineEdit::focusOutEvent(QFocusEvent* event) +void NumericLineEdit::focusOutEvent(QFocusEvent* e) { updateValue(); - QLineEdit::focusOutEvent(event); + QLineEdit::focusOutEvent(e); +} + +/// +/// \brief NumericLineEdit::keyPressEvent +/// \param e +/// +void NumericLineEdit::keyPressEvent(QKeyEvent* e) +{ + QLineEdit::keyPressEvent(e); } /// @@ -357,7 +379,7 @@ void NumericLineEdit::on_rangeChanged(const QVariant& bottom, const QVariant& to { const int nums = QString::number(top.toUInt(), 16).length(); _paddingZeroWidth = qMax(1, nums); - setMaxLength(qMax(1, nums)); + setMaxLength(qMax(1, nums + 2)); setValidator(new QHexValidator(bottom.toUInt(), top.toUInt(), this)); } break; diff --git a/omodscan/controls/numericlineedit.h b/omodscan/controls/numericlineedit.h index cf35aa8..fb072e6 100644 --- a/omodscan/controls/numericlineedit.h +++ b/omodscan/controls/numericlineedit.h @@ -59,7 +59,9 @@ class NumericLineEdit : public QLineEdit void rangeChanged(const QVariant& bottom, const QVariant& top); protected: + void focusInEvent(QFocusEvent*) override; void focusOutEvent(QFocusEvent*) override; + void keyPressEvent(QKeyEvent*) override; private slots: void on_editingFinished(); diff --git a/omodscan/dialogs/dialogusermsg.cpp b/omodscan/dialogs/dialogusermsg.cpp index 1395d8b..194880f 100644 --- a/omodscan/dialogs/dialogusermsg.cpp +++ b/omodscan/dialogs/dialogusermsg.cpp @@ -119,8 +119,6 @@ void DialogUserMsg::on_radioButtonHex_clicked(bool checked) { if(checked) { - ui->lineEditSlaveAddress->setPaddingZeroes(true); - ui->lineEditSlaveAddress->setInputMode(NumericLineEdit::HexMode); ui->comboBoxFunction->setInputMode(FunctionCodeComboBox::HexMode); ui->sendData->setInputMode(ByteListTextEdit::HexMode); ui->responseBuffer->setInputMode(ByteListTextEdit::HexMode); @@ -136,8 +134,6 @@ void DialogUserMsg::on_radioButtonDecimal_clicked(bool checked) { if(checked) { - ui->lineEditSlaveAddress->setPaddingZeroes(false); - ui->lineEditSlaveAddress->setInputMode(NumericLineEdit::DecMode); ui->comboBoxFunction->setInputMode(FunctionCodeComboBox::DecMode); ui->sendData->setInputMode(ByteListTextEdit::DecMode); ui->responseBuffer->setInputMode(ByteListTextEdit::DecMode); diff --git a/omodscan/formatutils.h b/omodscan/formatutils.h index 25907e7..47408cc 100644 --- a/omodscan/formatutils.h +++ b/omodscan/formatutils.h @@ -9,24 +9,6 @@ #include "numericutils.h" #include "byteorderutils.h" -/// -/// \brief formatFuncCode -/// \param mode -/// \param c -/// \return -/// -inline QString formatFuncCode(DataDisplayMode mode, QModbusPdu::FunctionCode c) -{ - switch(mode) - { - case DataDisplayMode::Decimal: - case DataDisplayMode::Integer: - return QString("%1").arg(QString::number(c), 2, '0'); - - default: - return QString("%1").arg(QString::number(c, 16).toUpper(), 2, '0'); - } -} /// /// \brief formatByteValue @@ -43,7 +25,7 @@ inline QString formatByteValue(DataDisplayMode mode, uchar c) return QString("%1").arg(QString::number(c), 3, '0'); default: - return QString("%1").arg(QString::number(c, 16).toUpper(), 2, '0'); + return QString("0x%1").arg(QString::number(c, 16).toUpper(), 2, '0'); } } @@ -56,8 +38,18 @@ inline QString formatByteValue(DataDisplayMode mode, uchar c) inline QString formatByteArray(DataDisplayMode mode, const QByteArray& ar) { QStringList values; - for(auto&& i : ar) - values += formatByteValue(mode, i); + for(uchar i : ar) + switch(mode) + { + case DataDisplayMode::Decimal: + case DataDisplayMode::Integer: + values += QString("%1").arg(QString::number(i), 3, '0'); + break; + + default: + values += QString("%1").arg(QString::number(i, 16).toUpper(), 2, '0'); + break; + } return values.join(" "); } @@ -77,7 +69,7 @@ inline QString formatWordValue(DataDisplayMode mode, quint16 v) return QString("%1").arg(QString::number(v), 3, '0'); default: - return QString("%1").arg(QString::number(v, 16).toUpper(), 2, '0'); + return QString("0x%1").arg(QString::number(v, 16).toUpper(), 2, '0'); } } @@ -95,16 +87,16 @@ inline QString formatBinaryValue(QModbusDataUnit::RegisterType pointType, quint1 switch(pointType) { - case QModbusDataUnit::Coils: - case QModbusDataUnit::DiscreteInputs: - result = QString("<%1>").arg(value); - break; - case QModbusDataUnit::HoldingRegisters: - case QModbusDataUnit::InputRegisters: - result = QStringLiteral("<%1>").arg(value, 16, 2, QLatin1Char('0')); - break; - default: - break; + case QModbusDataUnit::Coils: + case QModbusDataUnit::DiscreteInputs: + result = QString("<%1>").arg(value); + break; + case QModbusDataUnit::HoldingRegisters: + case QModbusDataUnit::InputRegisters: + result = QStringLiteral("<%1>").arg(value, 16, 2, QLatin1Char('0')); + break; + default: + break; } outValue = value; return result; @@ -124,16 +116,16 @@ inline QString formatDecimalValue(QModbusDataUnit::RegisterType pointType, quint switch(pointType) { - case QModbusDataUnit::Coils: - case QModbusDataUnit::DiscreteInputs: - result = QStringLiteral("<%1>").arg(value, 1, 10, QLatin1Char('0')); - break; - case QModbusDataUnit::HoldingRegisters: - case QModbusDataUnit::InputRegisters: - result = QStringLiteral("<%1>").arg(value, 5, 10, QLatin1Char('0')); - break; - default: - break; + case QModbusDataUnit::Coils: + case QModbusDataUnit::DiscreteInputs: + result = QStringLiteral("<%1>").arg(value, 1, 10, QLatin1Char('0')); + break; + case QModbusDataUnit::HoldingRegisters: + case QModbusDataUnit::InputRegisters: + result = QStringLiteral("<%1>").arg(value, 5, 10, QLatin1Char('0')); + break; + default: + break; } outValue = value; return result; @@ -153,16 +145,16 @@ inline QString formatIntegerValue(QModbusDataUnit::RegisterType pointType, qint1 switch(pointType) { - case QModbusDataUnit::Coils: - case QModbusDataUnit::DiscreteInputs: - result = QString("<%1>").arg(value); - break; - case QModbusDataUnit::HoldingRegisters: - case QModbusDataUnit::InputRegisters: - result = QStringLiteral("<%1>").arg(value, 5, 10, QLatin1Char(' ')); - break; - default: - break; + case QModbusDataUnit::Coils: + case QModbusDataUnit::DiscreteInputs: + result = QString("<%1>").arg(value); + break; + case QModbusDataUnit::HoldingRegisters: + case QModbusDataUnit::InputRegisters: + result = QStringLiteral("<%1>").arg(value, 5, 10, QLatin1Char(' ')); + break; + default: + break; } outValue = value; return result; @@ -182,19 +174,19 @@ inline QString formatHexValue(QModbusDataUnit::RegisterType pointType, quint16 v switch(pointType) { - case QModbusDataUnit::Coils: - case QModbusDataUnit::DiscreteInputs: - result = QString("<%1>").arg(value); - break; - case QModbusDataUnit::HoldingRegisters: - case QModbusDataUnit::InputRegisters: - result = QStringLiteral("<%1H>").arg(value, 4, 16, QLatin1Char('0')); - break; - default: - break; + case QModbusDataUnit::Coils: + case QModbusDataUnit::DiscreteInputs: + result = QString("<%1>").arg(value); + break; + case QModbusDataUnit::HoldingRegisters: + case QModbusDataUnit::InputRegisters: + result = QString("<0x%1>").arg(QString::number(value, 16).toUpper(), 4, '0'); + break; + default: + break; } outValue = value; - return result.toUpper(); + return result; } /// @@ -212,23 +204,23 @@ inline QString formatFloatValue(QModbusDataUnit::RegisterType pointType, quint16 QString result; switch(pointType) { - case QModbusDataUnit::Coils: - case QModbusDataUnit::DiscreteInputs: - outValue = value1; - result = QString("<%1>").arg(value1); - break; - case QModbusDataUnit::HoldingRegisters: - case QModbusDataUnit::InputRegisters: - { - if(flag) break; + case QModbusDataUnit::Coils: + case QModbusDataUnit::DiscreteInputs: + outValue = value1; + result = QString("<%1>").arg(value1); + break; + case QModbusDataUnit::HoldingRegisters: + case QModbusDataUnit::InputRegisters: + { + if(flag) break; - const float value = makeFloat(value1, value2, order); - outValue = value; - result = QLocale().toString(value); - } - break; - default: + const float value = makeFloat(value1, value2, order); + outValue = value; + result = QLocale().toString(value); + } break; + default: + break; } return result; } @@ -248,23 +240,23 @@ inline QString formatLongValue(QModbusDataUnit::RegisterType pointType, quint16 QString result; switch(pointType) { - case QModbusDataUnit::Coils: - case QModbusDataUnit::DiscreteInputs: - outValue = value1; - result = QString("<%1>").arg(value1); - break; - case QModbusDataUnit::HoldingRegisters: - case QModbusDataUnit::InputRegisters: - { - if(flag) break; + case QModbusDataUnit::Coils: + case QModbusDataUnit::DiscreteInputs: + outValue = value1; + result = QString("<%1>").arg(value1); + break; + case QModbusDataUnit::HoldingRegisters: + case QModbusDataUnit::InputRegisters: + { + if(flag) break; - const qint32 value = makeLong(value1, value2, order); - outValue = value; - result = result = QString("<%1>").arg(value, 10, 10, QLatin1Char(' ')); - } - break; - default: + const qint32 value = makeLong(value1, value2, order); + outValue = value; + result = result = QString("<%1>").arg(value, 10, 10, QLatin1Char(' ')); + } break; + default: + break; } return result; } @@ -284,23 +276,23 @@ inline QString formatUnsignedLongValue(QModbusDataUnit::RegisterType pointType, QString result; switch(pointType) { - case QModbusDataUnit::Coils: - case QModbusDataUnit::DiscreteInputs: - outValue = value1; - result = QString("<%1>").arg(value1); - break; - case QModbusDataUnit::HoldingRegisters: - case QModbusDataUnit::InputRegisters: - { - if(flag) break; + case QModbusDataUnit::Coils: + case QModbusDataUnit::DiscreteInputs: + outValue = value1; + result = QString("<%1>").arg(value1); + break; + case QModbusDataUnit::HoldingRegisters: + case QModbusDataUnit::InputRegisters: + { + if(flag) break; - const quint32 value = makeULong(value1, value2, order); - outValue = value; - result = result = QString("<%1>").arg(value, 10, 10, QLatin1Char('0')); - } - break; - default: + const quint32 value = makeULong(value1, value2, order); + outValue = value; + result = result = QString("<%1>").arg(value, 10, 10, QLatin1Char('0')); + } break; + default: + break; } return result; } @@ -322,23 +314,23 @@ inline QString formatDoubleValue(QModbusDataUnit::RegisterType pointType, quint1 QString result; switch(pointType) { - case QModbusDataUnit::Coils: - case QModbusDataUnit::DiscreteInputs: - outValue = value1; - result = QString("<%1>").arg(value1); - break; - case QModbusDataUnit::HoldingRegisters: - case QModbusDataUnit::InputRegisters: - { - if(flag) break; + case QModbusDataUnit::Coils: + case QModbusDataUnit::DiscreteInputs: + outValue = value1; + result = QString("<%1>").arg(value1); + break; + case QModbusDataUnit::HoldingRegisters: + case QModbusDataUnit::InputRegisters: + { + if(flag) break; - const double value = makeDouble(value1, value2, value3, value4, order); - outValue = value; - result = QLocale().toString(value, 'g', 16); - } - break; - default: + const double value = makeDouble(value1, value2, value3, value4, order); + outValue = value; + result = QLocale().toString(value, 'g', 16); + } break; + default: + break; } return result; } @@ -355,23 +347,23 @@ inline QString formatAddress(QModbusDataUnit::RegisterType pointType, int addres QString prefix; switch(pointType) { - case QModbusDataUnit::Coils: - prefix = "0"; - break; - case QModbusDataUnit::DiscreteInputs: - prefix = "1"; - break; - case QModbusDataUnit::HoldingRegisters: - prefix = "4"; - break; - case QModbusDataUnit::InputRegisters: - prefix = "3"; - break; - default: - break; + case QModbusDataUnit::Coils: + prefix = "0"; + break; + case QModbusDataUnit::DiscreteInputs: + prefix = "1"; + break; + case QModbusDataUnit::HoldingRegisters: + prefix = "4"; + break; + case QModbusDataUnit::InputRegisters: + prefix = "3"; + break; + default: + break; } - return hexFormat ? QStringLiteral("%1H").arg(address, 4, 16, QLatin1Char('0')) : + return hexFormat ? QString("<0x%1>").arg(QString::number(address, 16).toUpper(), 4, '0') : prefix + QStringLiteral("%1").arg(address, 4, 10, QLatin1Char('0')); } diff --git a/omodscan/qhexvalidator.cpp b/omodscan/qhexvalidator.cpp index 9d2be3e..7b00af4 100644 --- a/omodscan/qhexvalidator.cpp +++ b/omodscan/qhexvalidator.cpp @@ -9,6 +9,12 @@ QHexValidator::QHexValidator(QObject *parent) { } +/// +/// \brief QHexValidator::QHexValidator +/// \param bottom +/// \param top +/// \param parent +/// QHexValidator::QHexValidator(int bottom, int top, QObject* parent) : QIntValidator(bottom, top, parent) { From 65f4fc11dd32515a6133015213d886a0ac8e678e Mon Sep 17 00:00:00 2001 From: sanny32 Date: Thu, 5 Oct 2023 14:52:58 +0300 Subject: [PATCH 47/90] Refactoring --- omodscan/modbusclient.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/omodscan/modbusclient.cpp b/omodscan/modbusclient.cpp index bb8736c..ba9f18a 100644 --- a/omodscan/modbusclient.cpp +++ b/omodscan/modbusclient.cpp @@ -622,7 +622,7 @@ void ModbusClient::on_writeReply() if (reply->error() == QModbusDevice::ProtocolError) { ModbusException ex(raw.exceptionCode()); - emit modbusError(QString("%1. %2 (0x%3)").arg(errorDesc, ex, formatByteValue(DataDisplayMode::Hex, ex)), requestId); + emit modbusError(QString("%1. %2 (%3)").arg(errorDesc, ex, formatByteValue(DataDisplayMode::Hex, ex)), requestId); } else if(reply->error() != QModbusDevice::NoError) emit modbusError(QString("%1. %2").arg(errorDesc, reply->errorString()), requestId); From 133b39475fe735e7b739e1f843f8ac16fe242975 Mon Sep 17 00:00:00 2001 From: sanny32 Date: Thu, 5 Oct 2023 14:54:52 +0300 Subject: [PATCH 48/90] Refactoring --- omodscan/mainwindow.cpp | 9 +++++---- omodscan/mainwindow.h | 2 +- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/omodscan/mainwindow.cpp b/omodscan/mainwindow.cpp index 469439b..b7c90d2 100644 --- a/omodscan/mainwindow.cpp +++ b/omodscan/mainwindow.cpp @@ -48,7 +48,7 @@ MainWindow::MainWindow(QWidget *parent) const auto defaultPrinter = QPrinterInfo::defaultPrinter(); if(!defaultPrinter.isNull()) - _selectedPrinter = QSharedPointer(new QPrinter(defaultPrinter)); + _selectedPrinter = new QPrinter(defaultPrinter); _recentFileActionList = new RecentFileActionList(ui->menuFile, ui->actionRecentFile); connect(_recentFileActionList, &RecentFileActionList::triggered, this, &MainWindow::openFile); @@ -75,6 +75,7 @@ MainWindow::MainWindow(QWidget *parent) MainWindow::~MainWindow() { delete ui; + delete _selectedPrinter; } /// @@ -348,10 +349,10 @@ void MainWindow::on_actionPrint_triggered() auto frm = currentMdiChild(); if(!frm) return; - QPrintDialog dlg(_selectedPrinter.get(), this); + QPrintDialog dlg(_selectedPrinter, this); if(dlg.exec() == QDialog::Accepted) { - frm->print(_selectedPrinter.get()); + frm->print(_selectedPrinter); } } @@ -360,7 +361,7 @@ void MainWindow::on_actionPrint_triggered() /// void MainWindow::on_actionPrintSetup_triggered() { - DialogPrintSettings dlg(_selectedPrinter.get(), this); + DialogPrintSettings dlg(_selectedPrinter, this); dlg.exec(); } diff --git a/omodscan/mainwindow.h b/omodscan/mainwindow.h index 86dafb7..c7694fd 100644 --- a/omodscan/mainwindow.h +++ b/omodscan/mainwindow.h @@ -148,7 +148,7 @@ private slots: WindowActionList* _windowActionList; RecentFileActionList* _recentFileActionList; - QSharedPointer _selectedPrinter; + QPrinter* _selectedPrinter; DataSimulator* _dataSimulator; }; #endif // MAINWINDOW_H From edf70639d7e841ddc4b020831ac8ee076a624b5f Mon Sep 17 00:00:00 2001 From: sanny32 Date: Thu, 5 Oct 2023 15:49:14 +0300 Subject: [PATCH 49/90] Fixed bug to switch input mode --- omodscan/controls/functioncodecombobox.cpp | 66 +++++++++++++++------- omodscan/controls/functioncodecombobox.h | 1 + 2 files changed, 46 insertions(+), 21 deletions(-) diff --git a/omodscan/controls/functioncodecombobox.cpp b/omodscan/controls/functioncodecombobox.cpp index 1184054..09b8319 100644 --- a/omodscan/controls/functioncodecombobox.cpp +++ b/omodscan/controls/functioncodecombobox.cpp @@ -1,8 +1,6 @@ #include #include #include "modbusfunction.h" -#include "enums.h" -#include "formatutils.h" #include "qhexvalidator.h" #include "quintvalidator.h" #include "functioncodecombobox.h" @@ -81,6 +79,16 @@ void FunctionCodeComboBox::setInputMode(FunctionCodeComboBox::InputMode mode) break; } + blockSignals(true); + lineEdit()->blockSignals(true); + for (int i = 0; i < count(); i++) + { + const auto funcCode = itemData(i).value(); + setItemText(i, QString("%1: %2").arg(formatFuncCode(funcCode), ModbusFunction(funcCode))); + } + blockSignals(false); + lineEdit()->blockSignals(false); + update(); } @@ -116,19 +124,11 @@ void FunctionCodeComboBox::addAllItems() /// void FunctionCodeComboBox::update() { - if(currentData(Qt::DisplayRole) != currentText()) - { - const auto idx = findData(_currentFunc); - if(idx != -1) setCurrentIndex(idx); - else setCurrentText(formatFuncCode(_currentFunc)); - } - - for (int i = 0; i < count(); i++) - { - const auto funcCode = itemData(i).value(); - const auto code = formatFuncCode( funcCode); - setItemText(i, QString("%1: %2").arg(code, ModbusFunction(funcCode))); - } + const auto idx = findData(_currentFunc, Qt::UserRole); + if(idx != -1) + setCurrentIndex(idx); + else + setCurrentText(formatFuncCode(_currentFunc)); } /// @@ -138,8 +138,17 @@ void FunctionCodeComboBox::update() /// QString FunctionCodeComboBox::formatFuncCode(QModbusPdu::FunctionCode funcCode) const { - const auto mode = (_inputMode == InputMode::HexMode) ? DataDisplayMode::Hex : DataDisplayMode::Decimal; - return ::formatFuncCode(mode, funcCode); + switch(_inputMode) + { + case DecMode: + return QString("%1").arg(QString::number(funcCode), 2, '0'); + + case HexMode: + return (isEditable() && hasFocus() ? "" : "0x") + QString("%1").arg(QString::number(funcCode, 16).toUpper(), 2, '0'); + + default: + return QString::number(funcCode); + } } /// @@ -148,8 +157,11 @@ QString FunctionCodeComboBox::formatFuncCode(QModbusPdu::FunctionCode funcCode) /// void FunctionCodeComboBox::on_currentIndexChanged(int index) { - _currentFunc = itemData(index).value(); - emit functionCodeChanged(_currentFunc); + if(index >= 0) + { + _currentFunc = itemData(index).value(); + emit functionCodeChanged(_currentFunc); + } } /// @@ -171,17 +183,29 @@ void FunctionCodeComboBox::on_currentTextChanged(const QString& text) { case InputMode::DecMode: func = text.toUInt(&ok); - break; + break; case InputMode::HexMode: func = text.toUInt(&ok, 16); - break; + break; } _currentFunc = ok ? (QModbusPdu::FunctionCode)func : QModbusPdu::Invalid; } } +/// +/// \brief FunctionCodeComboBox::focusInEvent +/// \param e +/// +void FunctionCodeComboBox::focusInEvent(QFocusEvent* e) +{ + if(isEditable()) + setCurrentText(formatFuncCode(_currentFunc)); + + QComboBox::focusInEvent(e); +} + /// /// \brief FunctionCodeComboBox::focusOutEvent /// \param e diff --git a/omodscan/controls/functioncodecombobox.h b/omodscan/controls/functioncodecombobox.h index 3786612..1d48353 100644 --- a/omodscan/controls/functioncodecombobox.h +++ b/omodscan/controls/functioncodecombobox.h @@ -30,6 +30,7 @@ class FunctionCodeComboBox : public QComboBox void functionCodeChanged(QModbusPdu::FunctionCode funcCode); protected: + void focusInEvent(QFocusEvent* e) override; void focusOutEvent(QFocusEvent* e) override; void keyPressEvent(QKeyEvent* e) override; From 4f6208d4497abe6153bc256934fd5b1bee12f64c Mon Sep 17 00:00:00 2001 From: sanny32 Date: Thu, 5 Oct 2023 15:53:22 +0300 Subject: [PATCH 50/90] Correct warning --- omodscan/controls/functioncodecombobox.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/omodscan/controls/functioncodecombobox.cpp b/omodscan/controls/functioncodecombobox.cpp index 09b8319..12cc762 100644 --- a/omodscan/controls/functioncodecombobox.cpp +++ b/omodscan/controls/functioncodecombobox.cpp @@ -177,7 +177,7 @@ void FunctionCodeComboBox::on_currentTextChanged(const QString& text) else { bool ok; - quint8 func; + quint8 func = 0; switch(_inputMode) { From ceebaaea964646a3a8085ac307ceb80ae9c3fcaa Mon Sep 17 00:00:00 2001 From: sanny32 Date: Thu, 5 Oct 2023 16:10:18 +0300 Subject: [PATCH 51/90] Correct ModbusFunction --- omodscan/controls/functioncodecombobox.cpp | 15 ++++----------- omodscan/controls/functioncodecombobox.h | 2 +- omodscan/dialogs/dialogusermsg.cpp | 2 +- omodscan/modbusfunction.h | 13 ++++++++++++- omodscan/modbusmessages/modbusmessage.h | 2 +- 5 files changed, 19 insertions(+), 15 deletions(-) diff --git a/omodscan/controls/functioncodecombobox.cpp b/omodscan/controls/functioncodecombobox.cpp index 12cc762..ef2680f 100644 --- a/omodscan/controls/functioncodecombobox.cpp +++ b/omodscan/controls/functioncodecombobox.cpp @@ -103,19 +103,12 @@ void FunctionCodeComboBox::addItem(QModbusPdu::FunctionCode funcCode) } /// -/// \brief FunctionCodeComboBox::addAllItems +/// \brief FunctionCodeComboBox::addItems +/// \param funcCodes /// -void FunctionCodeComboBox::addAllItems() +void FunctionCodeComboBox::addItems(const QVector& funcCodes) { - static const auto items = { - QModbusPdu::ReadCoils, QModbusPdu::ReadDiscreteInputs, QModbusPdu::ReadHoldingRegisters, QModbusPdu::ReadInputRegisters, - QModbusPdu::WriteSingleCoil, QModbusPdu::WriteSingleRegister, QModbusPdu::ReadExceptionStatus, QModbusPdu::Diagnostics, - QModbusPdu::GetCommEventCounter, QModbusPdu::GetCommEventLog, QModbusPdu::WriteMultipleCoils, QModbusPdu::WriteMultipleRegisters, - QModbusPdu::ReportServerId, QModbusPdu::ReadFileRecord, QModbusPdu::WriteFileRecord, QModbusPdu::MaskWriteRegister, - QModbusPdu::ReadWriteMultipleRegisters, QModbusPdu::ReadFifoQueue, QModbusPdu::EncapsulatedInterfaceTransport - }; - - for(auto&& item : items) + for(auto&& item : funcCodes) addItem(item); } diff --git a/omodscan/controls/functioncodecombobox.h b/omodscan/controls/functioncodecombobox.h index 1d48353..595f22b 100644 --- a/omodscan/controls/functioncodecombobox.h +++ b/omodscan/controls/functioncodecombobox.h @@ -24,7 +24,7 @@ class FunctionCodeComboBox : public QComboBox void setInputMode(InputMode mode); void addItem(QModbusPdu::FunctionCode funcCode); - void addAllItems(); + void addItems(const QVector& funcCodes); signals: void functionCodeChanged(QModbusPdu::FunctionCode funcCode); diff --git a/omodscan/dialogs/dialogusermsg.cpp b/omodscan/dialogs/dialogusermsg.cpp index 194880f..fa48d38 100644 --- a/omodscan/dialogs/dialogusermsg.cpp +++ b/omodscan/dialogs/dialogusermsg.cpp @@ -28,7 +28,7 @@ DialogUserMsg::DialogUserMsg(quint8 slaveAddress, QModbusPdu::FunctionCode func, ui->lineEditSlaveAddress->setInputRange(ModbusLimits::slaveRange()); ui->lineEditSlaveAddress->setValue(slaveAddress); - ui->comboBoxFunction->addAllItems(); + ui->comboBoxFunction->addItems(ModbusFunction::validCodes()); ui->comboBoxFunction->setCurrentFunctionCode(func); ui->responseInfo->setShowTimestamp(false); diff --git a/omodscan/modbusfunction.h b/omodscan/modbusfunction.h index 7d58c76..b210a5b 100644 --- a/omodscan/modbusfunction.h +++ b/omodscan/modbusfunction.h @@ -14,9 +14,20 @@ class ModbusFunction { } + static QVector validCodes() { + static const QVector codes = { + QModbusPdu::ReadCoils, QModbusPdu::ReadDiscreteInputs, QModbusPdu::ReadHoldingRegisters, QModbusPdu::ReadInputRegisters, + QModbusPdu::WriteSingleCoil, QModbusPdu::WriteSingleRegister, QModbusPdu::ReadExceptionStatus, QModbusPdu::Diagnostics, + QModbusPdu::GetCommEventCounter, QModbusPdu::GetCommEventLog, QModbusPdu::WriteMultipleCoils, QModbusPdu::WriteMultipleRegisters, + QModbusPdu::ReportServerId, QModbusPdu::ReadFileRecord, QModbusPdu::WriteFileRecord, QModbusPdu::MaskWriteRegister, + QModbusPdu::ReadWriteMultipleRegisters, QModbusPdu::ReadFifoQueue, QModbusPdu::EncapsulatedInterfaceTransport + }; + return codes; + } + bool isValid() const { - return _code >= 1 && _code <= 0x2B; + return validCodes().contains(_code); } bool isException() const diff --git a/omodscan/modbusmessages/modbusmessage.h b/omodscan/modbusmessages/modbusmessage.h index 7fbab0b..0e1fa6f 100644 --- a/omodscan/modbusmessages/modbusmessage.h +++ b/omodscan/modbusmessages/modbusmessage.h @@ -91,7 +91,7 @@ class ModbusMessage /// \return /// bool isException() const { - return _funcCode & QModbusPdu::ExceptionByte; + return !isRequest() && (_funcCode & QModbusPdu::ExceptionByte); } /// From c2d5aca65ee8d490a064507930f6c947a4ec7694 Mon Sep 17 00:00:00 2001 From: sanny32 Date: Thu, 5 Oct 2023 16:47:56 +0300 Subject: [PATCH 52/90] Correct format hex addresses --- omodscan/formatutils.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/omodscan/formatutils.h b/omodscan/formatutils.h index 47408cc..011b653 100644 --- a/omodscan/formatutils.h +++ b/omodscan/formatutils.h @@ -363,7 +363,7 @@ inline QString formatAddress(QModbusDataUnit::RegisterType pointType, int addres break; } - return hexFormat ? QString("<0x%1>").arg(QString::number(address, 16).toUpper(), 4, '0') : + return hexFormat ? QString("0x%1").arg(QString::number(address, 16).toUpper(), 4, '0') : prefix + QStringLiteral("%1").arg(address, 4, 10, QLatin1Char('0')); } From 87df31b092a8e127de33dab4038efc58133be2a7 Mon Sep 17 00:00:00 2001 From: sanny32 Date: Thu, 5 Oct 2023 16:52:05 +0300 Subject: [PATCH 53/90] Correct log when scan modbus addresses --- omodscan/dialogs/dialogaddressscan.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/omodscan/dialogs/dialogaddressscan.cpp b/omodscan/dialogs/dialogaddressscan.cpp index 215069c..751d638 100644 --- a/omodscan/dialogs/dialogaddressscan.cpp +++ b/omodscan/dialogs/dialogaddressscan.cpp @@ -593,7 +593,7 @@ void DialogAddressScan::updateLogView(int deviceId, const QModbusRequest& reques request.decodeData(&pointAddress); auto proxyLogModel = ((LogViewProxyModel*)ui->logView->model()); - proxyLogModel->append(pointAddress, ui->comboBoxPointType->currentPointType(), + proxyLogModel->append(pointAddress + 1, ui->comboBoxPointType->currentPointType(), ModbusMessage::create(request, QDateTime::currentDateTime(), deviceId, true)); } From 9ce1cc3e01d7f91f59637c6dcaaf9d464b21eddc Mon Sep 17 00:00:00 2001 From: sanny32 Date: Thu, 5 Oct 2023 17:11:42 +0300 Subject: [PATCH 54/90] Correct format values --- omodscan/formatutils.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/omodscan/formatutils.h b/omodscan/formatutils.h index 011b653..fa90c30 100644 --- a/omodscan/formatutils.h +++ b/omodscan/formatutils.h @@ -16,7 +16,7 @@ /// \param c /// \return /// -inline QString formatByteValue(DataDisplayMode mode, uchar c) +inline QString formatByteValue(DataDisplayMode mode, quint8 c) { switch(mode) { @@ -38,7 +38,7 @@ inline QString formatByteValue(DataDisplayMode mode, uchar c) inline QString formatByteArray(DataDisplayMode mode, const QByteArray& ar) { QStringList values; - for(uchar i : ar) + for(quint8 i : ar) switch(mode) { case DataDisplayMode::Decimal: @@ -66,10 +66,10 @@ inline QString formatWordValue(DataDisplayMode mode, quint16 v) { case DataDisplayMode::Decimal: case DataDisplayMode::Integer: - return QString("%1").arg(QString::number(v), 3, '0'); + return QString("%1").arg(QString::number(v), 5, '0'); default: - return QString("0x%1").arg(QString::number(v, 16).toUpper(), 2, '0'); + return QString("0x%1").arg(QString::number(v, 16).toUpper(), 4, '0'); } } From 1b390bd7619b7b6e589d464e45511963c9ebd267 Mon Sep 17 00:00:00 2001 From: ananev-aa Date: Thu, 5 Oct 2023 18:43:44 +0300 Subject: [PATCH 55/90] Correct FunctionCodeComboBox display items when it is not editable --- omodscan/controls/functioncodecombobox.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/omodscan/controls/functioncodecombobox.cpp b/omodscan/controls/functioncodecombobox.cpp index ef2680f..458734f 100644 --- a/omodscan/controls/functioncodecombobox.cpp +++ b/omodscan/controls/functioncodecombobox.cpp @@ -57,11 +57,11 @@ FunctionCodeComboBox::InputMode FunctionCodeComboBox::inputMode() const /// void FunctionCodeComboBox::setInputMode(FunctionCodeComboBox::InputMode mode) { + _inputMode = mode; + if(!isEditable()) return; - _inputMode = mode; - if(_validator) { delete _validator; From 257015e36928294d72cc5617aa4a31207dc12c27 Mon Sep 17 00:00:00 2001 From: ananev-aa Date: Thu, 5 Oct 2023 21:23:24 +0300 Subject: [PATCH 56/90] Correct center pos of dialog --- omodscan/qfixedsizedialog.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/omodscan/qfixedsizedialog.cpp b/omodscan/qfixedsizedialog.cpp index f542e16..e694821 100644 --- a/omodscan/qfixedsizedialog.cpp +++ b/omodscan/qfixedsizedialog.cpp @@ -25,7 +25,7 @@ void QFixedSizeDialog::showEvent(QShowEvent* e) if(parentWidget() != nullptr) { - QRect parentRect(parentWidget()->mapToGlobal(QPoint(0, 0)), parentWidget()->size()); - move(QStyle::alignedRect(Qt::LeftToRight, Qt::AlignCenter, size(), parentRect).topLeft()); + const auto rc = parentWidget()->frameGeometry(); + move(rc.center() - rect().center()); } } From dd61b714db7626c08897747688addf82a47b10d4 Mon Sep 17 00:00:00 2001 From: ananev-aa Date: Thu, 5 Oct 2023 21:23:37 +0300 Subject: [PATCH 57/90] Correct dialog ui --- omodscan/dialogs/dialogmodbusscanner.ui | 51 +++++++++++++++++++------ 1 file changed, 39 insertions(+), 12 deletions(-) diff --git a/omodscan/dialogs/dialogmodbusscanner.ui b/omodscan/dialogs/dialogmodbusscanner.ui index db20b5c..aa65252 100644 --- a/omodscan/dialogs/dialogmodbusscanner.ui +++ b/omodscan/dialogs/dialogmodbusscanner.ui @@ -7,7 +7,7 @@ 0 0 707 - 863 + 810 @@ -204,15 +204,28 @@ Address Range - - + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + Qt::AlignHCenter|Qt::AlignTop + + from - + + + + to + + + + @@ -226,16 +239,15 @@ 25 - - - - - - to + + + 100 + 16777215 + - + @@ -249,6 +261,12 @@ 25 + + + 100 + 16777215 + + @@ -285,6 +303,12 @@ Port Range + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + Qt::AlignHCenter|Qt::AlignTop + @@ -356,7 +380,7 @@ - 150 + 152 60 @@ -559,6 +583,9 @@ font-weight: bold; Device Id + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + Qt::AlignHCenter|Qt::AlignTop From 2afeca996e1bb794204945425c7ee31df4c8fd90 Mon Sep 17 00:00:00 2001 From: ananev-aa Date: Thu, 5 Oct 2023 21:31:55 +0300 Subject: [PATCH 58/90] Correct UserMsg dialog ui --- omodscan/dialogs/dialogusermsg.ui | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/omodscan/dialogs/dialogusermsg.ui b/omodscan/dialogs/dialogusermsg.ui index 1e53247..73a8a9a 100644 --- a/omodscan/dialogs/dialogusermsg.ui +++ b/omodscan/dialogs/dialogusermsg.ui @@ -200,6 +200,9 @@ 3 + + Qt::NoFocus + QAbstractItemView::NoEditTriggers @@ -231,6 +234,11 @@ + + FunctionCodeComboBox + QComboBox +
functioncodecombobox.h
+
NumericLineEdit QLineEdit @@ -246,11 +254,6 @@ QPlainTextEdit
bytelisttextedit.h
- - FunctionCodeComboBox - QComboBox -
functioncodecombobox.h
-
radioButtonDecimal From 1054d01cb87cfb12fd980b5128c94e809509f82c Mon Sep 17 00:00:00 2001 From: ananev-aa Date: Thu, 5 Oct 2023 22:09:30 +0300 Subject: [PATCH 59/90] Developing view register values at log --- omodscan/controls/modbusmessagewidget.cpp | 24 +++++++++++++++- omodscan/controls/modbusmessagewidget.h | 4 +++ omodscan/controls/outputwidget.cpp | 2 ++ omodscan/dialogs/dialogdisplaydefinition.cpp | 23 ++++++++-------- omodscan/dialogs/dialogdisplaydefinition.h | 7 ++++- omodscan/formatutils.h | 29 ++++++++++++++++++++ omodscan/formmodsca.cpp | 7 +++-- omodscan/formmodsca.h | 1 + omodscan/mainwindow.cpp | 5 ++-- omodscan/numericutils.h | 4 +-- 10 files changed, 85 insertions(+), 21 deletions(-) diff --git a/omodscan/controls/modbusmessagewidget.cpp b/omodscan/controls/modbusmessagewidget.cpp index 9748327..bb44c8f 100644 --- a/omodscan/controls/modbusmessagewidget.cpp +++ b/omodscan/controls/modbusmessagewidget.cpp @@ -9,8 +9,11 @@ /// ModbusMessageWidget::ModbusMessageWidget(QWidget *parent) : QListWidget(parent) + ,_byteOrder(ByteOrder::LittleEndian) + ,_dataDisplayMode(DataDisplayMode::Decimal) ,_showTimestamp(true) ,_msg(nullptr) + { setItemDelegate(new HtmlDelegate(this)); setEditTriggers(QAbstractItemView::NoEditTriggers); @@ -44,6 +47,25 @@ void ModbusMessageWidget::setDataDisplayMode(DataDisplayMode mode) update(); } +/// +/// \brief ModbusMessageWidget::byteOrder +/// \return +/// +ByteOrder ModbusMessageWidget::byteOrder() const +{ + return _byteOrder; +} + +/// +/// \brief ModbusMessageWidget::setByteOrder +/// \param order +/// +void ModbusMessageWidget::setByteOrder(ByteOrder order) +{ + _byteOrder = order; + update(); +} + /// /// \brief ModbusMessageWidget::showTimestamp /// \return @@ -171,7 +193,7 @@ void ModbusMessageWidget::update() { auto resp = reinterpret_cast(_msg); const auto byteCount = resp->isValid() ? formatByteValue(_dataDisplayMode, resp->byteCount()) : "?"; - const auto registerValue = resp->isValid() ? formatByteArray(_dataDisplayMode, resp->registerValue()) : "???"; + const auto registerValue = resp->isValid() ? formatWordArray(_dataDisplayMode, resp->registerValue(), _byteOrder) : "???"; addItem(tr("Byte Count: %1").arg(byteCount)); addItem(tr("Register Value: %1").arg(registerValue)); } diff --git a/omodscan/controls/modbusmessagewidget.h b/omodscan/controls/modbusmessagewidget.h index cba2060..25fc53b 100644 --- a/omodscan/controls/modbusmessagewidget.h +++ b/omodscan/controls/modbusmessagewidget.h @@ -18,6 +18,9 @@ class ModbusMessageWidget : public QListWidget DataDisplayMode dataDisplayMode() const; void setDataDisplayMode(DataDisplayMode mode); + ByteOrder byteOrder() const; + void setByteOrder(ByteOrder order); + const ModbusMessage* modbusMessage() const; void setModbusMessage(const ModbusMessage* msg); @@ -28,6 +31,7 @@ class ModbusMessageWidget : public QListWidget void update(); private: + ByteOrder _byteOrder; DataDisplayMode _dataDisplayMode; bool _showTimestamp; const ModbusMessage* _msg; diff --git a/omodscan/controls/outputwidget.cpp b/omodscan/controls/outputwidget.cpp index a84abd7..03547c7 100644 --- a/omodscan/controls/outputwidget.cpp +++ b/omodscan/controls/outputwidget.cpp @@ -711,6 +711,8 @@ ByteOrder OutputWidget::byteOrder() const void OutputWidget::setByteOrder(ByteOrder order) { _byteOrder = order; + ui->modbusMsg->setByteOrder(order); + _listModel->update(); } diff --git a/omodscan/dialogs/dialogdisplaydefinition.cpp b/omodscan/dialogs/dialogdisplaydefinition.cpp index 9febb67..08818c5 100644 --- a/omodscan/dialogs/dialogdisplaydefinition.cpp +++ b/omodscan/dialogs/dialogdisplaydefinition.cpp @@ -5,11 +5,13 @@ /// /// \brief DialogDisplayDefinition::DialogDisplayDefinition +/// \param dd /// \param parent /// -DialogDisplayDefinition::DialogDisplayDefinition(FormModSca* parent) : - QFixedSizeDialog(parent), - ui(new Ui::DialogDisplayDefinition) +DialogDisplayDefinition::DialogDisplayDefinition(DisplayDefinition dd, QWidget* parent) + : QFixedSizeDialog(parent) + ,_displayDefinition(dd) + , ui(new Ui::DialogDisplayDefinition) { ui->setupUi(this); ui->lineEditScanRate->setInputRange(20, 36000000); @@ -18,7 +20,6 @@ DialogDisplayDefinition::DialogDisplayDefinition(FormModSca* parent) : ui->lineEditSlaveAddress->setInputRange(ModbusLimits::slaveRange()); ui->lineEditLogLimit->setInputRange(4, 1000); - const auto dd = parent->displayDefinition(); ui->lineEditScanRate->setValue(dd.ScanRate); ui->lineEditPointAddress->setValue(dd.PointAddress); ui->lineEditSlaveAddress->setValue(dd.DeviceId); @@ -42,14 +43,12 @@ DialogDisplayDefinition::~DialogDisplayDefinition() /// void DialogDisplayDefinition::accept() { - DisplayDefinition dd; - dd.DeviceId = ui->lineEditSlaveAddress->value(); - dd.PointAddress = ui->lineEditPointAddress->value(); - dd.PointType = ui->comboBoxPointType->currentPointType(); - dd.Length = ui->lineEditLength->value(); - dd.ScanRate = ui->lineEditScanRate->value(); - dd.LogViewLimit = ui->lineEditLogLimit->value(); - ((FormModSca*)parentWidget())->setDisplayDefinition(dd); + _displayDefinition.DeviceId = ui->lineEditSlaveAddress->value(); + _displayDefinition.PointAddress = ui->lineEditPointAddress->value(); + _displayDefinition.PointType = ui->comboBoxPointType->currentPointType(); + _displayDefinition.Length = ui->lineEditLength->value(); + _displayDefinition.ScanRate = ui->lineEditScanRate->value(); + _displayDefinition.LogViewLimit = ui->lineEditLogLimit->value(); QFixedSizeDialog::accept(); } diff --git a/omodscan/dialogs/dialogdisplaydefinition.h b/omodscan/dialogs/dialogdisplaydefinition.h index 3edd82b..f3fc3bb 100644 --- a/omodscan/dialogs/dialogdisplaydefinition.h +++ b/omodscan/dialogs/dialogdisplaydefinition.h @@ -16,12 +16,17 @@ class DialogDisplayDefinition : public QFixedSizeDialog Q_OBJECT public: - explicit DialogDisplayDefinition(FormModSca* parent); + explicit DialogDisplayDefinition(DisplayDefinition dd, QWidget* parent); ~DialogDisplayDefinition(); + DisplayDefinition displayDefinition() const { + return _displayDefinition; + } + void accept() override; private: + DisplayDefinition _displayDefinition; Ui::DialogDisplayDefinition *ui; }; diff --git a/omodscan/formatutils.h b/omodscan/formatutils.h index fa90c30..739be6d 100644 --- a/omodscan/formatutils.h +++ b/omodscan/formatutils.h @@ -54,6 +54,35 @@ inline QString formatByteArray(DataDisplayMode mode, const QByteArray& ar) return values.join(" "); } +/// +/// \brief formatWordArray +/// \param mode +/// \param ar +/// \param order +/// \return +/// +inline QString formatWordArray(DataDisplayMode mode, const QByteArray& ar, ByteOrder order) +{ + QStringList values; + for(int i = 0; i < ar.size(); i+=2) + { + const quint16 value = makeWord(ar[i+1], ar[i], order); + switch(mode) + { + case DataDisplayMode::Decimal: + case DataDisplayMode::Integer: + values += QString("%1").arg(QString::number(value), 5, '0'); + break; + + default: + values += QString("%1").arg(QString::number(value, 16).toUpper(), 4, '0'); + break; + } + } + + return values.join(" "); +} + /// /// \brief formatWordValue /// \param mode diff --git a/omodscan/formmodsca.cpp b/omodscan/formmodsca.cpp index e1f7b0a..d35defb 100644 --- a/omodscan/formmodsca.cpp +++ b/omodscan/formmodsca.cpp @@ -27,6 +27,7 @@ FormModSca::FormModSca(int id, ModbusClient& client, DataSimulator* simulator, M ,_noSlaveResponsesCounter(0) ,_modbusClient(client) ,_dataSimulator(simulator) + ,_parent(parent) { Q_ASSERT(parent != nullptr); Q_ASSERT(simulator != nullptr); @@ -748,7 +749,7 @@ void FormModSca::on_outputWidget_itemDoubleClicked(quint16 addr, const QVariant& case QModbusDataUnit::Coils: { ModbusWriteParams params = { node, addr, value, mode, byteOrder() }; - DialogWriteCoilRegister dlg(params, simParams, this); + DialogWriteCoilRegister dlg(params, simParams, _parent); switch(dlg.exec()) { case QDialog::Accepted: @@ -768,13 +769,13 @@ void FormModSca::on_outputWidget_itemDoubleClicked(quint16 addr, const QVariant& ModbusWriteParams params = { node, addr, value, mode, byteOrder()}; if(mode == DataDisplayMode::Binary) { - DialogWriteHoldingRegisterBits dlg(params, this); + DialogWriteHoldingRegisterBits dlg(params, _parent); if(dlg.exec() == QDialog::Accepted) _modbusClient.writeRegister(pointType, params, _formId); } else { - DialogWriteHoldingRegister dlg(params, simParams, mode, this); + DialogWriteHoldingRegister dlg(params, simParams, mode, _parent); switch(dlg.exec()) { case QDialog::Accepted: diff --git a/omodscan/formmodsca.h b/omodscan/formmodsca.h index 03df814..cbdb865 100644 --- a/omodscan/formmodsca.h +++ b/omodscan/formmodsca.h @@ -135,6 +135,7 @@ private slots: QString _filename; ModbusClient& _modbusClient; DataSimulator* _dataSimulator; + MainWindow* _parent; }; /// diff --git a/omodscan/mainwindow.cpp b/omodscan/mainwindow.cpp index b7c90d2..6cfd608 100644 --- a/omodscan/mainwindow.cpp +++ b/omodscan/mainwindow.cpp @@ -474,8 +474,9 @@ void MainWindow::on_actionDataDefinition_triggered() auto frm = currentMdiChild(); if(!frm) return; - DialogDisplayDefinition dlg(frm); - dlg.exec(); + DialogDisplayDefinition dlg(frm->displayDefinition(), this); + if(dlg.exec() == QDialog::Accepted) + frm->setDisplayDefinition(dlg.displayDefinition()); } /// diff --git a/omodscan/numericutils.h b/omodscan/numericutils.h index 06c9902..7a7b767 100644 --- a/omodscan/numericutils.h +++ b/omodscan/numericutils.h @@ -18,8 +18,8 @@ inline quint16 makeWord(quint8 lo, quint8 hi, ByteOrder order) quint16 asUint16; } v; - v.asUint8[0] = toByteOrderValue(lo, order); - v.asUint8[1] = toByteOrderValue(hi, order); + v.asUint8[0] = (order == ByteOrder::LittleEndian) ? lo : hi; + v.asUint8[1] = (order == ByteOrder::LittleEndian) ? hi : lo; return v.asUint16; } From c7a2dad4803330051589011da1115843d6b48a15 Mon Sep 17 00:00:00 2001 From: ananev-aa Date: Fri, 6 Oct 2023 07:17:52 +0300 Subject: [PATCH 60/90] Improve modbus message info widget --- omodscan/controls/modbusmessagewidget.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/omodscan/controls/modbusmessagewidget.cpp b/omodscan/controls/modbusmessagewidget.cpp index bb44c8f..308715d 100644 --- a/omodscan/controls/modbusmessagewidget.cpp +++ b/omodscan/controls/modbusmessagewidget.cpp @@ -212,7 +212,7 @@ void ModbusMessageWidget::update() { auto resp = reinterpret_cast(_msg); const auto byteCount = resp->isValid() ? formatByteValue(_dataDisplayMode, resp->byteCount()) : "?"; - const auto registerValue = resp->isValid() ? formatByteArray(_dataDisplayMode, resp->registerValue()) : "???"; + const auto registerValue = resp->isValid() ? formatWordArray(_dataDisplayMode, resp->registerValue(), _byteOrder) : "???"; addItem(tr("Byte Count: %1").arg(byteCount)); addItem(tr("Input Registers: %1").arg(registerValue)); } @@ -342,7 +342,7 @@ void ModbusMessageWidget::update() const auto startAddr = req->isValid() ? formatWordValue(_dataDisplayMode, req->startAddress()) : "??"; const auto quantity = req->isValid() ? formatWordValue(_dataDisplayMode, req->quantity()) : "??"; const auto byteCount = req->isValid() ? formatByteValue(_dataDisplayMode, req->byteCount()) : "?"; - const auto values = req->isValid() ? formatByteArray(_dataDisplayMode, req->values()) : "???"; + const auto values = req->isValid() ? formatWordArray(_dataDisplayMode, req->values(), _byteOrder) : "???"; addItem(tr("Starting Address: %1").arg(startAddr)); addItem(tr("Quantity of Registers: %1").arg(quantity)); addItem(tr("Byte Count: %1").arg(byteCount)); @@ -439,7 +439,7 @@ void ModbusMessageWidget::update() const auto writeStartAddr = req->isValid() ? formatWordValue(_dataDisplayMode, req->writeStartAddress()) : "??"; const auto writeLength = req->isValid() ? formatWordValue(_dataDisplayMode, req->writeLength()) : "??"; const auto writeByteCount = req->isValid() ? formatByteValue(_dataDisplayMode, req->writeByteCount()) : "?"; - const auto writeValues = req->isValid() ? formatByteArray(_dataDisplayMode, req->writeValues()) : "???"; + const auto writeValues = req->isValid() ? formatWordArray(_dataDisplayMode, req->writeValues(), _byteOrder) : "???"; addItem(tr("Read Starting Address: %1").arg(readStartAddr)); addItem(tr("Quantity to Read: %1").arg(readLength)); addItem(tr("Write Starting Address: %1").arg(writeStartAddr)); @@ -451,7 +451,7 @@ void ModbusMessageWidget::update() { auto resp = reinterpret_cast(_msg); const auto byteCount = resp->isValid() ? formatByteValue(_dataDisplayMode, resp->byteCount()): "?"; - const auto values = resp->isValid() ? formatByteArray(_dataDisplayMode, resp->values()) : "???"; + const auto values = resp->isValid() ? formatWordArray(_dataDisplayMode, resp->values(), _byteOrder) : "???"; addItem(tr("Byte Count: %1").arg(byteCount)); addItem(tr("Registers Value: %1").arg(values)); } @@ -469,7 +469,7 @@ void ModbusMessageWidget::update() auto resp = reinterpret_cast(_msg); const auto byteCount = resp->isValid() ? formatByteValue(_dataDisplayMode, resp->byteCount()) : "?"; const auto fifoCount = resp->isValid() ? formatByteValue(_dataDisplayMode, resp->fifoCount()) : "?"; - const auto fifoValue = resp->isValid() ? formatByteArray(_dataDisplayMode, resp->fifoValue()) : "???"; + const auto fifoValue = resp->isValid() ? formatWordArray(_dataDisplayMode, resp->fifoValue(), _byteOrder) : "???"; addItem(tr("Byte Count: %1").arg(byteCount)); addItem(tr("FIFO Count: %1").arg(fifoCount)); addItem(tr("FIFO Value Register: %1").arg(fifoValue)); From a247d31c84ba8191b5d726bce42ea02e6475c46d Mon Sep 17 00:00:00 2001 From: sanny32 Date: Fri, 6 Oct 2023 15:10:38 +0300 Subject: [PATCH 61/90] Developing modbus message parser --- omodscan/dialogmsgparser.cpp | 14 ++++++++ omodscan/dialogmsgparser.h | 22 ++++++++++++ omodscan/dialogmsgparser.ui | 67 ++++++++++++++++++++++++++++++++++++ omodscan/mainwindow.cpp | 10 ++++++ omodscan/mainwindow.h | 1 + omodscan/mainwindow.ui | 12 +++++++ omodscan/omodscan.pro | 3 ++ 7 files changed, 129 insertions(+) create mode 100644 omodscan/dialogmsgparser.cpp create mode 100644 omodscan/dialogmsgparser.h create mode 100644 omodscan/dialogmsgparser.ui diff --git a/omodscan/dialogmsgparser.cpp b/omodscan/dialogmsgparser.cpp new file mode 100644 index 0000000..045239b --- /dev/null +++ b/omodscan/dialogmsgparser.cpp @@ -0,0 +1,14 @@ +#include "dialogmsgparser.h" +#include "ui_dialogmsgparser.h" + +DialogMsgParser::DialogMsgParser(QWidget *parent) : + QDialog(parent), + ui(new Ui::DialogMsgParser) +{ + ui->setupUi(this); +} + +DialogMsgParser::~DialogMsgParser() +{ + delete ui; +} diff --git a/omodscan/dialogmsgparser.h b/omodscan/dialogmsgparser.h new file mode 100644 index 0000000..ef2ab4d --- /dev/null +++ b/omodscan/dialogmsgparser.h @@ -0,0 +1,22 @@ +#ifndef DIALOGMSGPARSER_H +#define DIALOGMSGPARSER_H + +#include + +namespace Ui { +class DialogMsgParser; +} + +class DialogMsgParser : public QDialog +{ + Q_OBJECT + +public: + explicit DialogMsgParser(QWidget *parent = nullptr); + ~DialogMsgParser(); + +private: + Ui::DialogMsgParser *ui; +}; + +#endif // DIALOGMSGPARSER_H diff --git a/omodscan/dialogmsgparser.ui b/omodscan/dialogmsgparser.ui new file mode 100644 index 0000000..c06b302 --- /dev/null +++ b/omodscan/dialogmsgparser.ui @@ -0,0 +1,67 @@ + + + DialogMsgParser + + + + 0 + 0 + 530 + 304 + + + + Dialog + + + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + true + + + + + + + + + buttonBox + accepted() + DialogMsgParser + accept() + + + 248 + 254 + + + 157 + 274 + + + + + buttonBox + rejected() + DialogMsgParser + reject() + + + 316 + 260 + + + 286 + 274 + + + + + diff --git a/omodscan/mainwindow.cpp b/omodscan/mainwindow.cpp index 6cfd608..9403586 100644 --- a/omodscan/mainwindow.cpp +++ b/omodscan/mainwindow.cpp @@ -11,6 +11,7 @@ #include "dialogforcemultiplecoils.h" #include "dialogforcemultipleregisters.h" #include "dialogusermsg.h" +#include "dialogmsgparser.h" #include "dialogaddressscan.h" #include "dialogmodbusscanner.h" #include "dialogwindowsmanager.h" @@ -744,6 +745,15 @@ void MainWindow::on_actionUserMsg_triggered() dlg.exec(); } +/// +/// \brief MainWindow::on_actionMsgParser_triggered +/// +void MainWindow::on_actionMsgParser_triggered() +{ + DialogMsgParser dlg(this); + dlg.exec(); +} + /// /// \brief MainWindow::on_actionAddressScan_triggered /// diff --git a/omodscan/mainwindow.h b/omodscan/mainwindow.h index c7694fd..06347d4 100644 --- a/omodscan/mainwindow.h +++ b/omodscan/mainwindow.h @@ -76,6 +76,7 @@ private slots: void on_actionPresetRegs_triggered(); void on_actionMaskWrite_triggered(); void on_actionUserMsg_triggered(); + void on_actionMsgParser_triggered(); void on_actionAddressScan_triggered(); void on_actionTextCapture_triggered(); void on_actionCaptureOff_triggered(); diff --git a/omodscan/mainwindow.ui b/omodscan/mainwindow.ui index 6a02a70..49e847a 100644 --- a/omodscan/mainwindow.ui +++ b/omodscan/mainwindow.ui @@ -127,6 +127,7 @@ + @@ -755,6 +756,17 @@ Ctrl+Shift+5 + + + Msg Parser + + + Msg Parser + + + F9 + + diff --git a/omodscan/omodscan.pro b/omodscan/omodscan.pro index 35f1aeb..abd1c16 100644 --- a/omodscan/omodscan.pro +++ b/omodscan/omodscan.pro @@ -46,6 +46,7 @@ SOURCES += \ controls/outputwidget.cpp \ controls/pointtypecombobox.cpp \ datasimulator.cpp \ + dialogmsgparser.cpp \ dialogs/dialogabout.cpp \ dialogs/dialogaddressscan.cpp \ dialogs/dialogautosimulation.cpp \ @@ -106,6 +107,7 @@ HEADERS += \ controls/outputwidget.h \ controls/pointtypecombobox.h \ datasimulator.h \ + dialogmsgparser.h \ dialogs/dialogabout.h \ dialogs/dialogaddressscan.h \ dialogs/dialogautosimulation.h \ @@ -172,6 +174,7 @@ HEADERS += \ FORMS += \ controls/outputwidget.ui \ controls/statisticwidget.ui \ + dialogmsgparser.ui \ dialogs/dialogabout.ui \ dialogs/dialogaddressscan.ui \ dialogs/dialogautosimulation.ui \ From 6939629e18d913b0215f54c4c3e3a25f247d1d34 Mon Sep 17 00:00:00 2001 From: sanny32 Date: Fri, 6 Oct 2023 15:23:02 +0300 Subject: [PATCH 62/90] Developing modbus message parser --- omodscan/dialogmsgparser.ui | 96 +++++++++++++++++++++++++++++++++++-- 1 file changed, 92 insertions(+), 4 deletions(-) diff --git a/omodscan/dialogmsgparser.ui b/omodscan/dialogmsgparser.ui index c06b302..5a166e6 100644 --- a/omodscan/dialogmsgparser.ui +++ b/omodscan/dialogmsgparser.ui @@ -6,21 +6,97 @@ 0 0 - 530 - 304 + 662 + 412 - Dialog + Modbus Message Parser + + + + 0 + + + + PDU + + + + + + + + Request + + + + + + + Device Id Included + + + true + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + Qt::Vertical + + + + + 0 + 1 + + + + + + + 0 + 2 + + + + + + + + + + ADU + + + + Qt::Horizontal - QDialogButtonBox::Cancel|QDialogButtonBox::Ok + QDialogButtonBox::Close|QDialogButtonBox::Ok true @@ -29,6 +105,18 @@ + + + ModbusMessageWidget + QListWidget +
modbusmessagewidget.h
+
+ + ByteListTextEdit + QPlainTextEdit +
bytelisttextedit.h
+
+
From 8e96effe73768a48045335ab6fc3981c1e0ed254 Mon Sep 17 00:00:00 2001 From: sanny32 Date: Fri, 6 Oct 2023 15:44:14 +0300 Subject: [PATCH 63/90] Developing modbus message parser --- omodscan/dialogmsgparser.cpp | 22 ++++++++++++++++++++++ omodscan/dialogmsgparser.h | 2 ++ omodscan/dialogmsgparser.ui | 7 +++++-- 3 files changed, 29 insertions(+), 2 deletions(-) diff --git a/omodscan/dialogmsgparser.cpp b/omodscan/dialogmsgparser.cpp index 045239b..7c9560b 100644 --- a/omodscan/dialogmsgparser.cpp +++ b/omodscan/dialogmsgparser.cpp @@ -1,14 +1,36 @@ +#include #include "dialogmsgparser.h" #include "ui_dialogmsgparser.h" +/// +/// \brief DialogMsgParser::DialogMsgParser +/// \param parent +/// DialogMsgParser::DialogMsgParser(QWidget *parent) : QDialog(parent), ui(new Ui::DialogMsgParser) { ui->setupUi(this); + + setWindowFlags(Qt::Dialog | + Qt::CustomizeWindowHint | + Qt::WindowTitleHint); + + ui->buttonBox->button(QDialogButtonBox::Ok)->setText(tr("Parse")); } +/// +/// \brief DialogMsgParser::~DialogMsgParser +/// DialogMsgParser::~DialogMsgParser() { delete ui; } + +/// +/// \brief DialogMsgParser::accept +/// +void DialogMsgParser::accept() +{ + const auto data = ui->pduData->value(); +} diff --git a/omodscan/dialogmsgparser.h b/omodscan/dialogmsgparser.h index ef2ab4d..bda75a7 100644 --- a/omodscan/dialogmsgparser.h +++ b/omodscan/dialogmsgparser.h @@ -15,6 +15,8 @@ class DialogMsgParser : public QDialog explicit DialogMsgParser(QWidget *parent = nullptr); ~DialogMsgParser(); + void accept() override; + private: Ui::DialogMsgParser *ui; }; diff --git a/omodscan/dialogmsgparser.ui b/omodscan/dialogmsgparser.ui index 5a166e6..0fa8011 100644 --- a/omodscan/dialogmsgparser.ui +++ b/omodscan/dialogmsgparser.ui @@ -21,7 +21,7 @@ - PDU + Modbus PDU @@ -70,6 +70,9 @@ 1 + + Enter bytes value separated by spaces + @@ -85,7 +88,7 @@ - ADU + Modbus ADU From 8cefbd41bfd57decda818296d5e1fbb3e48321da Mon Sep 17 00:00:00 2001 From: ananev-aa Date: Fri, 6 Oct 2023 19:17:11 +0300 Subject: [PATCH 64/90] Developing modbus message parser --- omodscan/{ => dialogs}/dialogmsgparser.cpp | 14 ++++++++---- omodscan/{ => dialogs}/dialogmsgparser.h | 0 omodscan/{ => dialogs}/dialogmsgparser.ui | 0 omodscan/modbusmessages/modbusmessage.cpp | 25 ++++++++++++++++++++++ omodscan/modbusmessages/modbusmessage.h | 9 ++++++++ omodscan/omodscan.pro | 6 +++--- 6 files changed, 47 insertions(+), 7 deletions(-) rename omodscan/{ => dialogs}/dialogmsgparser.cpp (56%) rename omodscan/{ => dialogs}/dialogmsgparser.h (100%) rename omodscan/{ => dialogs}/dialogmsgparser.ui (100%) diff --git a/omodscan/dialogmsgparser.cpp b/omodscan/dialogs/dialogmsgparser.cpp similarity index 56% rename from omodscan/dialogmsgparser.cpp rename to omodscan/dialogs/dialogmsgparser.cpp index 7c9560b..bc1728b 100644 --- a/omodscan/dialogmsgparser.cpp +++ b/omodscan/dialogs/dialogmsgparser.cpp @@ -1,4 +1,5 @@ #include +#include "modbusmessage.h" #include "dialogmsgparser.h" #include "ui_dialogmsgparser.h" @@ -6,9 +7,9 @@ /// \brief DialogMsgParser::DialogMsgParser /// \param parent /// -DialogMsgParser::DialogMsgParser(QWidget *parent) : - QDialog(parent), - ui(new Ui::DialogMsgParser) +DialogMsgParser::DialogMsgParser(QWidget *parent) + : QDialog(parent) + , ui(new Ui::DialogMsgParser) { ui->setupUi(this); @@ -16,6 +17,7 @@ DialogMsgParser::DialogMsgParser(QWidget *parent) : Qt::CustomizeWindowHint | Qt::WindowTitleHint); + ui->pduInfo->setShowTimestamp(false); ui->buttonBox->button(QDialogButtonBox::Ok)->setText(tr("Parse")); } @@ -32,5 +34,9 @@ DialogMsgParser::~DialogMsgParser() /// void DialogMsgParser::accept() { - const auto data = ui->pduData->value(); + if(ui->pduInfo->modbusMessage()) + delete ui->pduInfo->modbusMessage(); + + const auto msg = ModbusMessage::parse(ui->pduData->value(), ui->deviceIdIncluded->isChecked(), ui->pduRequest->isChecked()); + ui->pduInfo->setModbusMessage(msg); } diff --git a/omodscan/dialogmsgparser.h b/omodscan/dialogs/dialogmsgparser.h similarity index 100% rename from omodscan/dialogmsgparser.h rename to omodscan/dialogs/dialogmsgparser.h diff --git a/omodscan/dialogmsgparser.ui b/omodscan/dialogs/dialogmsgparser.ui similarity index 100% rename from omodscan/dialogmsgparser.ui rename to omodscan/dialogs/dialogmsgparser.ui diff --git a/omodscan/modbusmessages/modbusmessage.cpp b/omodscan/modbusmessages/modbusmessage.cpp index 5e87957..63e3c68 100644 --- a/omodscan/modbusmessages/modbusmessage.cpp +++ b/omodscan/modbusmessages/modbusmessage.cpp @@ -88,3 +88,28 @@ const ModbusMessage* ModbusMessage::create(const QModbusPdu& pdu, const QDateTim return new ModbusMessage(pdu, timestamp, deviceId, request); } } + +/// +/// \brief ModbusMessage::parse +/// \param data +/// \param withDeviceId +/// \param request +/// \return +/// +const ModbusMessage* ModbusMessage::parse(const QByteArray& data, bool withDeviceId, bool request) +{ + QModbusPdu pdu; + + if(withDeviceId) + { + pdu.setFunctionCode((QModbusPdu::FunctionCode)data[1]); + if(data.size() > 1) pdu.setData(data.right(data.size() - 1)); + + return create(pdu, QDateTime::currentDateTime(), data[0], request); + } + else + { + pdu.setFunctionCode((QModbusPdu::FunctionCode)data[0]); + return create(pdu, QDateTime::currentDateTime(), -1, request); + } +} diff --git a/omodscan/modbusmessages/modbusmessage.h b/omodscan/modbusmessages/modbusmessage.h index 0e1fa6f..c41e0a6 100644 --- a/omodscan/modbusmessages/modbusmessage.h +++ b/omodscan/modbusmessages/modbusmessage.h @@ -46,6 +46,15 @@ class ModbusMessage /// static const ModbusMessage* create(const QModbusPdu& pdu, const QDateTime& timestamp, int deviceId, bool request); + /// + /// \brief parse + /// \param data + /// \param withDeviceId + /// \param request + /// \return + /// + static const ModbusMessage* parse(const QByteArray& data, bool withDeviceId, bool request); + /// /// \brief isValid /// \return diff --git a/omodscan/omodscan.pro b/omodscan/omodscan.pro index abd1c16..547e461 100644 --- a/omodscan/omodscan.pro +++ b/omodscan/omodscan.pro @@ -46,7 +46,7 @@ SOURCES += \ controls/outputwidget.cpp \ controls/pointtypecombobox.cpp \ datasimulator.cpp \ - dialogmsgparser.cpp \ + dialogs/dialogmsgparser.cpp \ dialogs/dialogabout.cpp \ dialogs/dialogaddressscan.cpp \ dialogs/dialogautosimulation.cpp \ @@ -107,7 +107,7 @@ HEADERS += \ controls/outputwidget.h \ controls/pointtypecombobox.h \ datasimulator.h \ - dialogmsgparser.h \ + dialogs/dialogmsgparser.h \ dialogs/dialogabout.h \ dialogs/dialogaddressscan.h \ dialogs/dialogautosimulation.h \ @@ -174,7 +174,7 @@ HEADERS += \ FORMS += \ controls/outputwidget.ui \ controls/statisticwidget.ui \ - dialogmsgparser.ui \ + dialogs/dialogmsgparser.ui \ dialogs/dialogabout.ui \ dialogs/dialogaddressscan.ui \ dialogs/dialogautosimulation.ui \ From 1735fcfe9fab0ced9a453fc0b7139fb9515bc2d4 Mon Sep 17 00:00:00 2001 From: sanny32 Date: Mon, 9 Oct 2023 11:28:50 +0300 Subject: [PATCH 65/90] Developing modbus message parser --- omodscan/controls/bytelisttextedit.cpp | 1 + omodscan/controls/bytelisttextedit.h | 4 + omodscan/dialogs/dialogmsgparser.cpp | 37 +++- omodscan/dialogs/dialogmsgparser.h | 10 +- omodscan/dialogs/dialogmsgparser.ui | 200 ++++++++++++++-------- omodscan/mainwindow.cpp | 8 +- omodscan/modbusmessages/modbusmessage.cpp | 6 +- omodscan/modbusmessages/modbusmessage.h | 3 +- 8 files changed, 183 insertions(+), 86 deletions(-) diff --git a/omodscan/controls/bytelisttextedit.cpp b/omodscan/controls/bytelisttextedit.cpp index b2d8e32..edac53b 100644 --- a/omodscan/controls/bytelisttextedit.cpp +++ b/omodscan/controls/bytelisttextedit.cpp @@ -156,6 +156,7 @@ void ByteListTextEdit::keyPressEvent(QKeyEvent *e) if(state == QValidator::Acceptable || e->key() == Qt::Key_Backspace || e->key() == Qt::Key_Delete || + e->key() == Qt::Key_Space || e->matches(QKeySequence::Cut) || e->matches(QKeySequence::Copy) || e->matches(QKeySequence::Paste) || diff --git a/omodscan/controls/bytelisttextedit.h b/omodscan/controls/bytelisttextedit.h index 1b7ea2c..b589af7 100644 --- a/omodscan/controls/bytelisttextedit.h +++ b/omodscan/controls/bytelisttextedit.h @@ -30,6 +30,10 @@ class ByteListTextEdit : public QPlainTextEdit QString text() const; void setText(const QString& text); + bool isEmpty() const { + return text().isEmpty(); + } + signals: void valueChanged(const QByteArray& value); diff --git a/omodscan/dialogs/dialogmsgparser.cpp b/omodscan/dialogs/dialogmsgparser.cpp index bc1728b..1eebc73 100644 --- a/omodscan/dialogs/dialogmsgparser.cpp +++ b/omodscan/dialogs/dialogmsgparser.cpp @@ -1,13 +1,15 @@ #include +#include #include "modbusmessage.h" #include "dialogmsgparser.h" #include "ui_dialogmsgparser.h" /// /// \brief DialogMsgParser::DialogMsgParser +/// \param mode /// \param parent /// -DialogMsgParser::DialogMsgParser(QWidget *parent) +DialogMsgParser::DialogMsgParser(DataDisplayMode mode, QWidget *parent) : QDialog(parent) , ui(new Ui::DialogMsgParser) { @@ -17,8 +19,12 @@ DialogMsgParser::DialogMsgParser(QWidget *parent) Qt::CustomizeWindowHint | Qt::WindowTitleHint); - ui->pduInfo->setShowTimestamp(false); + ui->info->setShowTimestamp(false); ui->buttonBox->button(QDialogButtonBox::Ok)->setText(tr("Parse")); + ui->hexView->setCheckState(mode == DataDisplayMode::Hex ? Qt::Checked : Qt::Unchecked); + + auto dispatcher = QAbstractEventDispatcher::instance(); + connect(dispatcher, &QAbstractEventDispatcher::awake, this, &DialogMsgParser::on_awake); } /// @@ -29,14 +35,33 @@ DialogMsgParser::~DialogMsgParser() delete ui; } +/// +/// \brief DialogMsgParser::on_awake +/// +void DialogMsgParser::on_awake() +{ + ui->deviceIdIncluded->setVisible(ui->buttonPdu->isChecked()); + ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(!ui->bytesData->isEmpty()); +} + +/// +/// \brief DialogMsgParser::on_hexView_toggled +/// \param checked +/// +void DialogMsgParser::on_hexView_toggled(bool checked) +{ + ui->bytesData->setInputMode(checked ? ByteListTextEdit::HexMode : ByteListTextEdit::DecMode); + ui->info->setDataDisplayMode(checked ? DataDisplayMode::Hex : DataDisplayMode::Decimal); +} + /// /// \brief DialogMsgParser::accept /// void DialogMsgParser::accept() { - if(ui->pduInfo->modbusMessage()) - delete ui->pduInfo->modbusMessage(); + if(ui->info->modbusMessage()) + delete ui->info->modbusMessage(); - const auto msg = ModbusMessage::parse(ui->pduData->value(), ui->deviceIdIncluded->isChecked(), ui->pduRequest->isChecked()); - ui->pduInfo->setModbusMessage(msg); + const auto msg = ModbusMessage::parse(ui->bytesData->value(), ui->deviceIdIncluded->isChecked(), ui->pduRequest->isChecked()); + ui->info->setModbusMessage(msg); } diff --git a/omodscan/dialogs/dialogmsgparser.h b/omodscan/dialogs/dialogmsgparser.h index bda75a7..c1eede6 100644 --- a/omodscan/dialogs/dialogmsgparser.h +++ b/omodscan/dialogs/dialogmsgparser.h @@ -2,21 +2,29 @@ #define DIALOGMSGPARSER_H #include +#include "enums.h" namespace Ui { class DialogMsgParser; } +/// +/// \brief The DialogMsgParser class +/// class DialogMsgParser : public QDialog { Q_OBJECT public: - explicit DialogMsgParser(QWidget *parent = nullptr); + explicit DialogMsgParser(DataDisplayMode mode, QWidget *parent = nullptr); ~DialogMsgParser(); void accept() override; +private slots: + void on_awake(); + void on_hexView_toggled(bool); + private: Ui::DialogMsgParser *ui; }; diff --git a/omodscan/dialogs/dialogmsgparser.ui b/omodscan/dialogs/dialogmsgparser.ui index 0fa8011..ec00d62 100644 --- a/omodscan/dialogs/dialogmsgparser.ui +++ b/omodscan/dialogs/dialogmsgparser.ui @@ -7,7 +7,7 @@ 0 0 662 - 412 + 424 @@ -15,81 +15,133 @@ - - - 0 + + + + + PDU Message + + + true + + + true + + + true + + + false + + + false + + + + + + + ADU Message + + + true + + + true + + + false + + + false + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + Qt::RightToLeft + + + Hex View + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Request + + + + + + + Device Id Included + + + true + + + + + + + + + Qt::Vertical - - - Modbus PDU - - - - - - - - Request - - - - - - - Device Id Included - - - true - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - Qt::Vertical - - - - - 0 - 1 - - - - Enter bytes value separated by spaces - - - - - - 0 - 2 - - - - - - + + + + 0 + 1 + + + + Enter bytes value separated by spaces + - - - Modbus ADU - + + + + 0 + 2 + + + + true + diff --git a/omodscan/mainwindow.cpp b/omodscan/mainwindow.cpp index 9403586..6ee0a78 100644 --- a/omodscan/mainwindow.cpp +++ b/omodscan/mainwindow.cpp @@ -750,8 +750,12 @@ void MainWindow::on_actionUserMsg_triggered() /// void MainWindow::on_actionMsgParser_triggered() { - DialogMsgParser dlg(this); - dlg.exec(); + auto frm = currentMdiChild(); + const auto mode = frm ? frm->dataDisplayMode() : DataDisplayMode::Hex; + + auto dlg = new DialogMsgParser(mode, this); + dlg->setAttribute(Qt::WA_DeleteOnClose, true); + dlg->show(); } /// diff --git a/omodscan/modbusmessages/modbusmessage.cpp b/omodscan/modbusmessages/modbusmessage.cpp index 63e3c68..23578e1 100644 --- a/omodscan/modbusmessages/modbusmessage.cpp +++ b/omodscan/modbusmessages/modbusmessage.cpp @@ -103,13 +103,15 @@ const ModbusMessage* ModbusMessage::parse(const QByteArray& data, bool withDevic if(withDeviceId) { pdu.setFunctionCode((QModbusPdu::FunctionCode)data[1]); - if(data.size() > 1) pdu.setData(data.right(data.size() - 1)); + if(data.size() > 2) pdu.setData(data.right(data.size() - 2)); return create(pdu, QDateTime::currentDateTime(), data[0], request); } else { pdu.setFunctionCode((QModbusPdu::FunctionCode)data[0]); - return create(pdu, QDateTime::currentDateTime(), -1, request); + if(data.size() > 1) pdu.setData(data.right(data.size() - 1)); + + return create(pdu, QDateTime::currentDateTime(), 0, request); } } diff --git a/omodscan/modbusmessages/modbusmessage.h b/omodscan/modbusmessages/modbusmessage.h index c41e0a6..905b096 100644 --- a/omodscan/modbusmessages/modbusmessage.h +++ b/omodscan/modbusmessages/modbusmessage.h @@ -3,6 +3,7 @@ #include #include +#include "modbuslimits.h" #include "formatutils.h" #include "modbusfunction.h" #include "modbusexception.h" @@ -60,7 +61,7 @@ class ModbusMessage /// \return /// virtual bool isValid() const { - return _deviceId >= 0 && _isValid; + return (_deviceId == 0 || ModbusLimits::slaveRange().contains(_deviceId)) && _isValid; } /// From fa8e495d321bbb5b74962449a6ba6b4140e7a423 Mon Sep 17 00:00:00 2001 From: sanny32 Date: Mon, 9 Oct 2023 16:50:39 +0300 Subject: [PATCH 66/90] Developing modbus message parser --- omodscan/controls/modbusmessagewidget.cpp | 8 + omodscan/dialogs/dialogmsgparser.cpp | 16 +- omodscan/dialogs/dialogmsgparser.ui | 9 +- omodscan/modbusmessages/diagnostics.h | 38 +++- omodscan/modbusmessages/getcommeventcounter.h | 32 +++- omodscan/modbusmessages/getcommeventlog.h | 38 +++- omodscan/modbusmessages/maskwriteregister.h | 42 +++-- omodscan/modbusmessages/modbusmessage.cpp | 121 +++++++++++-- omodscan/modbusmessages/modbusmessage.h | 153 ++++++++++++++-- omodscan/modbusmessages/readcoils.h | 38 +++- omodscan/modbusmessages/readdiscreteinputs.h | 38 +++- omodscan/modbusmessages/readexceptionstatus.h | 30 +++- omodscan/modbusmessages/readfifoqueue.h | 38 +++- omodscan/modbusmessages/readfilerecord.h | 38 +++- .../modbusmessages/readholdingregisters.h | 38 +++- omodscan/modbusmessages/readinputregisters.h | 38 +++- .../readwritemultipleregisters.h | 46 +++-- omodscan/modbusmessages/reportserverid.h | 32 +++- omodscan/modbusmessages/writefilerecord.h | 38 +++- omodscan/modbusmessages/writemultiplecoils.h | 42 +++-- .../modbusmessages/writemultipleregisters.h | 42 +++-- omodscan/modbusmessages/writesinglecoil.h | 38 +++- omodscan/modbusmessages/writesingleregister.h | 38 +++- omodscan/numericutils.h | 19 ++ omodscan/omodscan.pro | 1 + omodscan/qmodbusadu.h | 163 ++++++++++++++++++ 26 files changed, 1003 insertions(+), 171 deletions(-) create mode 100644 omodscan/qmodbusadu.h diff --git a/omodscan/controls/modbusmessagewidget.cpp b/omodscan/controls/modbusmessagewidget.cpp index 308715d..fa6eabc 100644 --- a/omodscan/controls/modbusmessagewidget.cpp +++ b/omodscan/controls/modbusmessagewidget.cpp @@ -124,6 +124,14 @@ void ModbusMessageWidget::update() addItem(tr("Type: %1").arg(_msg->isRequest() ? tr("Tx Message") : tr("Rx Message"))); if(_showTimestamp) addItem(tr("Timestamp: %1").arg(_msg->timestamp().toString(Qt::ISODateWithMs))); + + if(_msg->type() == ModbusMessage::Adu) + { + addItem(tr("Transaction ID: %1").arg(formatWordValue(_dataDisplayMode, _msg->transactionId()))); + addItem(tr("Protocol ID: %1").arg(formatWordValue(_dataDisplayMode, _msg->protocolId()))); + addItem(tr("Length: %1").arg(formatWordValue(_dataDisplayMode, _msg->length()))); + } + addItem(tr("Device ID: %1").arg(formatByteValue(_dataDisplayMode, _msg->deviceId()))); if(_msg->isException()) diff --git a/omodscan/dialogs/dialogmsgparser.cpp b/omodscan/dialogs/dialogmsgparser.cpp index 1eebc73..8f18649 100644 --- a/omodscan/dialogs/dialogmsgparser.cpp +++ b/omodscan/dialogs/dialogmsgparser.cpp @@ -40,6 +40,7 @@ DialogMsgParser::~DialogMsgParser() /// void DialogMsgParser::on_awake() { + ui->rtu->setVisible(ui->buttonAdu->isChecked()); ui->deviceIdIncluded->setVisible(ui->buttonPdu->isChecked()); ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(!ui->bytesData->isEmpty()); } @@ -62,6 +63,19 @@ void DialogMsgParser::accept() if(ui->info->modbusMessage()) delete ui->info->modbusMessage(); - const auto msg = ModbusMessage::parse(ui->bytesData->value(), ui->deviceIdIncluded->isChecked(), ui->pduRequest->isChecked()); + const ModbusMessage* msg = nullptr; + if(ui->buttonPdu->isChecked()) + { + auto data = ui->bytesData->value(); + if(!ui->deviceIdIncluded->isChecked()) data.push_front('\0'); + msg = ModbusMessage::parse(data, ModbusMessage::Pdu, QModbusAdu::Tcp, ui->request->isChecked()); + } + else if(ui->buttonAdu->isChecked()) + { + auto data = ui->bytesData->value(); + const auto protocol = ui->rtu->isChecked() ? QModbusAdu::Rtu : QModbusAdu::Tcp; + msg = ModbusMessage::parse(data, ModbusMessage::Adu, protocol, ui->request->isChecked()); + } + ui->info->setModbusMessage(msg); } diff --git a/omodscan/dialogs/dialogmsgparser.ui b/omodscan/dialogs/dialogmsgparser.ui index ec00d62..fcfab9b 100644 --- a/omodscan/dialogs/dialogmsgparser.ui +++ b/omodscan/dialogs/dialogmsgparser.ui @@ -98,7 +98,14 @@
- + + + Modbus RTU + + + + + Request diff --git a/omodscan/modbusmessages/diagnostics.h b/omodscan/modbusmessages/diagnostics.h index 99351ef..481c862 100644 --- a/omodscan/modbusmessages/diagnostics.h +++ b/omodscan/modbusmessages/diagnostics.h @@ -18,7 +18,18 @@ class DiagnosticsRequest : public ModbusMessage DiagnosticsRequest(const QModbusPdu& pdu, const QDateTime& timestamp, int deviceId) : ModbusMessage(pdu, timestamp, deviceId, true) { - Q_ASSERT((_funcCode & ~QModbusPdu::ExceptionByte) == QModbusPdu::Diagnostics); + Q_ASSERT(functionCode() == QModbusPdu::Diagnostics); + } + + /// + /// \brief DiagnosticsRequest + /// \param adu + /// \param timestamp + /// + DiagnosticsRequest(const QModbusAdu& adu, const QDateTime& timestamp) + : ModbusMessage(adu, timestamp, true) + { + Q_ASSERT(functionCode() == QModbusPdu::Diagnostics); } /// @@ -26,7 +37,7 @@ class DiagnosticsRequest : public ModbusMessage /// \return /// bool isValid() const override { - return ModbusMessage::isValid() && _data.size() > 2; + return ModbusMessage::isValid() && dataSize() > 2; } @@ -35,7 +46,7 @@ class DiagnosticsRequest : public ModbusMessage /// \return /// quint16 subfunc() const { - return makeWord(_data[1], _data[0], ByteOrder::LittleEndian); + return makeWord(ModbusMessage::data(1), ModbusMessage::data(0), ByteOrder::LittleEndian); } /// @@ -43,7 +54,7 @@ class DiagnosticsRequest : public ModbusMessage /// \return /// QByteArray data() const { - return _data.right(_data.size() - 2); + return slice(2); } }; @@ -62,7 +73,18 @@ class DiagnosticsResponse : public ModbusMessage DiagnosticsResponse(const QModbusPdu& pdu, const QDateTime& timestamp, int deviceId) :ModbusMessage(pdu, timestamp, deviceId, false) { - Q_ASSERT((_funcCode & ~QModbusPdu::ExceptionByte) == QModbusPdu::Diagnostics); + Q_ASSERT(functionCode() == QModbusPdu::Diagnostics); + } + + /// + /// \brief DiagnosticsResponse + /// \param adu + /// \param timestamp + /// + DiagnosticsResponse(const QModbusAdu& adu, const QDateTime& timestamp) + : ModbusMessage(adu, timestamp, true) + { + Q_ASSERT(functionCode() == QModbusPdu::Diagnostics); } /// @@ -70,7 +92,7 @@ class DiagnosticsResponse : public ModbusMessage /// \return /// bool isValid() const override { - return ModbusMessage::isValid() && _data.size() > 2; + return ModbusMessage::isValid() && dataSize() > 2; } /// @@ -78,7 +100,7 @@ class DiagnosticsResponse : public ModbusMessage /// \return /// quint16 subfunc() const { - return makeWord(_data[1], _data[0], ByteOrder::LittleEndian); + return makeWord(ModbusMessage::data(1), ModbusMessage::data(0), ByteOrder::LittleEndian); } /// @@ -86,7 +108,7 @@ class DiagnosticsResponse : public ModbusMessage /// \return /// QByteArray data() const { - return _data.right(_data.size() - 2); + return slice(2); } }; diff --git a/omodscan/modbusmessages/getcommeventcounter.h b/omodscan/modbusmessages/getcommeventcounter.h index bc65f47..b820f3c 100644 --- a/omodscan/modbusmessages/getcommeventcounter.h +++ b/omodscan/modbusmessages/getcommeventcounter.h @@ -18,7 +18,18 @@ class GetCommEventCounterRequest : public ModbusMessage GetCommEventCounterRequest(const QModbusPdu& pdu, const QDateTime& timestamp, int deviceId) : ModbusMessage(pdu, timestamp, deviceId, true) { - Q_ASSERT((_funcCode & ~QModbusPdu::ExceptionByte) == QModbusPdu::GetCommEventCounter); + Q_ASSERT(functionCode() == QModbusPdu::GetCommEventCounter); + } + + /// + /// \brief GetCommEventCounterRequest + /// \param adu + /// \param timestamp + /// + GetCommEventCounterRequest(const QModbusAdu& adu, const QDateTime& timestamp) + : ModbusMessage(adu, timestamp, true) + { + Q_ASSERT(functionCode() == QModbusPdu::GetCommEventCounter); } }; @@ -37,7 +48,18 @@ class GetCommEventCounterResponse : public ModbusMessage GetCommEventCounterResponse(const QModbusPdu& pdu, const QDateTime& timestamp, int deviceId) :ModbusMessage(pdu, timestamp, deviceId, false) { - Q_ASSERT((_funcCode & ~QModbusPdu::ExceptionByte) == QModbusPdu::GetCommEventCounter); + Q_ASSERT(functionCode() == QModbusPdu::GetCommEventCounter); + } + + /// + /// \brief GetCommEventCounterResponse + /// \param adu + /// \param timestamp + /// + GetCommEventCounterResponse(const QModbusAdu& adu, const QDateTime& timestamp) + : ModbusMessage(adu, timestamp, true) + { + Q_ASSERT(functionCode() == QModbusPdu::GetCommEventCounter); } /// @@ -45,7 +67,7 @@ class GetCommEventCounterResponse : public ModbusMessage /// \return /// bool isValid() const override { - return ModbusMessage::isValid() && _data.size() == 4; + return ModbusMessage::isValid() && dataSize() == 4; } /// @@ -53,7 +75,7 @@ class GetCommEventCounterResponse : public ModbusMessage /// \return /// quint16 status() const { - return makeWord(_data[1], _data[0], ByteOrder::LittleEndian); + return makeWord(data(1), data(0), ByteOrder::LittleEndian); } /// @@ -61,7 +83,7 @@ class GetCommEventCounterResponse : public ModbusMessage /// \return /// quint16 eventCount() const { - return makeWord(_data[3], _data[2], ByteOrder::LittleEndian); + return makeWord(data(3), data(2), ByteOrder::LittleEndian); } }; diff --git a/omodscan/modbusmessages/getcommeventlog.h b/omodscan/modbusmessages/getcommeventlog.h index 8ee3281..6d3586f 100644 --- a/omodscan/modbusmessages/getcommeventlog.h +++ b/omodscan/modbusmessages/getcommeventlog.h @@ -18,7 +18,18 @@ class GetCommEventLogRequest : public ModbusMessage GetCommEventLogRequest(const QModbusPdu& pdu, const QDateTime& timestamp, int deviceId) : ModbusMessage(pdu, timestamp, deviceId, true) { - Q_ASSERT((_funcCode & ~QModbusPdu::ExceptionByte) == QModbusPdu::GetCommEventLog); + Q_ASSERT(functionCode() == QModbusPdu::GetCommEventLog); + } + + /// + /// \brief GetCommEventLogRequest + /// \param adu + /// \param timestamp + /// + GetCommEventLogRequest(const QModbusAdu& adu, const QDateTime& timestamp) + : ModbusMessage(adu, timestamp, true) + { + Q_ASSERT(functionCode() == QModbusPdu::GetCommEventLog); } }; @@ -37,7 +48,18 @@ class GetCommEventLogResponse : public ModbusMessage GetCommEventLogResponse(const QModbusPdu& pdu, const QDateTime& timestamp, int deviceId) :ModbusMessage(pdu, timestamp, deviceId, false) { - Q_ASSERT((_funcCode & ~QModbusPdu::ExceptionByte) == QModbusPdu::GetCommEventLog); + Q_ASSERT(functionCode() == QModbusPdu::GetCommEventLog); + } + + /// + /// \brief GetCommEventLogResponse + /// \param adu + /// \param timestamp + /// + GetCommEventLogResponse(const QModbusAdu& adu, const QDateTime& timestamp) + : ModbusMessage(adu, timestamp, true) + { + Q_ASSERT(functionCode() == QModbusPdu::GetCommEventLog); } /// @@ -45,7 +67,7 @@ class GetCommEventLogResponse : public ModbusMessage /// \return /// bool isValid() const override { - return ModbusMessage::isValid() && _data.size() > 7; + return ModbusMessage::isValid() && dataSize() > 7; } /// @@ -53,7 +75,7 @@ class GetCommEventLogResponse : public ModbusMessage /// \return /// quint8 byteCount() const { - return _data[0]; + return data(0); } /// @@ -61,7 +83,7 @@ class GetCommEventLogResponse : public ModbusMessage /// \return /// quint16 status() const { - return makeWord(_data[2], _data[1], ByteOrder::LittleEndian); + return makeWord(data(2), data(1), ByteOrder::LittleEndian); } /// @@ -69,7 +91,7 @@ class GetCommEventLogResponse : public ModbusMessage /// \return /// quint16 eventCount() const { - return makeWord(_data[4], _data[3], ByteOrder::LittleEndian); + return makeWord(data(4), data(3), ByteOrder::LittleEndian); } /// @@ -77,7 +99,7 @@ class GetCommEventLogResponse : public ModbusMessage /// \return /// quint16 messageCount() const { - return makeWord(_data[6], _data[5], ByteOrder::LittleEndian); + return makeWord(data(6), data(5), ByteOrder::LittleEndian); } /// @@ -85,7 +107,7 @@ class GetCommEventLogResponse : public ModbusMessage /// \return /// QByteArray events() const { - return _data.right(_data.size() - 7); + return slice(7); } }; diff --git a/omodscan/modbusmessages/maskwriteregister.h b/omodscan/modbusmessages/maskwriteregister.h index e1f2208..412b865 100644 --- a/omodscan/modbusmessages/maskwriteregister.h +++ b/omodscan/modbusmessages/maskwriteregister.h @@ -18,7 +18,18 @@ class MaskWriteRegisterRequest : public ModbusMessage MaskWriteRegisterRequest(const QModbusPdu& pdu, const QDateTime& timestamp, int deviceId) : ModbusMessage(pdu, timestamp, deviceId, true) { - Q_ASSERT((_funcCode & ~QModbusPdu::ExceptionByte) == QModbusPdu::MaskWriteRegister); + Q_ASSERT(functionCode() == QModbusPdu::MaskWriteRegister); + } + + /// + /// \brief MaskWriteRegisterRequest + /// \param adu + /// \param timestamp + /// + MaskWriteRegisterRequest(const QModbusAdu& adu, const QDateTime& timestamp) + : ModbusMessage(adu, timestamp, true) + { + Q_ASSERT(functionCode() == QModbusPdu::MaskWriteRegister); } /// @@ -26,7 +37,7 @@ class MaskWriteRegisterRequest : public ModbusMessage /// \return /// bool isValid() const override { - return ModbusMessage::isValid() && _data.size() == 6; + return ModbusMessage::isValid() && dataSize() == 6; } /// @@ -34,7 +45,7 @@ class MaskWriteRegisterRequest : public ModbusMessage /// \return /// quint16 address() const { - return makeWord(_data[1], _data[0], ByteOrder::LittleEndian); + return makeWord(data(1), data(0), ByteOrder::LittleEndian); } /// @@ -42,7 +53,7 @@ class MaskWriteRegisterRequest : public ModbusMessage /// \return /// quint16 andMask() const { - return makeWord(_data[3], _data[2], ByteOrder::LittleEndian); + return makeWord(data(3), data(2), ByteOrder::LittleEndian); } /// @@ -50,7 +61,7 @@ class MaskWriteRegisterRequest : public ModbusMessage /// \return /// quint16 orMask() const { - return makeWord(_data[5], _data[4], ByteOrder::LittleEndian); + return makeWord(data(5), data(4), ByteOrder::LittleEndian); } }; @@ -69,7 +80,18 @@ class MaskWriteRegisterResponse : public ModbusMessage MaskWriteRegisterResponse(const QModbusPdu& pdu, const QDateTime& timestamp, int deviceId) :ModbusMessage(pdu, timestamp, deviceId, false) { - Q_ASSERT((_funcCode & ~QModbusPdu::ExceptionByte) == QModbusPdu::MaskWriteRegister); + Q_ASSERT(functionCode() == QModbusPdu::MaskWriteRegister); + } + + /// + /// \brief MaskWriteRegisterResponse + /// \param adu + /// \param timestamp + /// + MaskWriteRegisterResponse(const QModbusAdu& adu, const QDateTime& timestamp) + : ModbusMessage(adu, timestamp, true) + { + Q_ASSERT(functionCode() == QModbusPdu::MaskWriteRegister); } /// @@ -77,7 +99,7 @@ class MaskWriteRegisterResponse : public ModbusMessage /// \return /// bool isValid() const override { - return ModbusMessage::isValid() && _data.size() == 6; + return ModbusMessage::isValid() && dataSize() == 6; } /// @@ -85,7 +107,7 @@ class MaskWriteRegisterResponse : public ModbusMessage /// \return /// quint16 address() const { - return makeWord(_data[1], _data[0], ByteOrder::LittleEndian); + return makeWord(data(1), data(0), ByteOrder::LittleEndian); } /// @@ -93,7 +115,7 @@ class MaskWriteRegisterResponse : public ModbusMessage /// \return /// quint16 andMask() const { - return makeWord(_data[3], _data[2], ByteOrder::LittleEndian); + return makeWord(data(3), data(2), ByteOrder::LittleEndian); } /// @@ -101,7 +123,7 @@ class MaskWriteRegisterResponse : public ModbusMessage /// \return /// quint16 orMask() const { - return makeWord(_data[5], _data[4], ByteOrder::LittleEndian); + return makeWord(data(5), data(4), ByteOrder::LittleEndian); } }; diff --git a/omodscan/modbusmessages/modbusmessage.cpp b/omodscan/modbusmessages/modbusmessage.cpp index 23578e1..a1df3ec 100644 --- a/omodscan/modbusmessages/modbusmessage.cpp +++ b/omodscan/modbusmessages/modbusmessage.cpp @@ -1,5 +1,6 @@ #include "modbusmessages.h" + /// /// \brief ModbusMessage::create /// \param pdu @@ -89,29 +90,123 @@ const ModbusMessage* ModbusMessage::create(const QModbusPdu& pdu, const QDateTim } } +/// +/// \brief ModbusMessage::create +/// \param adu +/// \param timestamp +/// \param request +/// \return +/// +const ModbusMessage* ModbusMessage::create(const QModbusAdu& adu, const QDateTime& timestamp, bool request) +{ + switch(adu.functionCode()) + { + case QModbusPdu::ReadCoils: + if(request) return new ReadCoilsRequest(adu, timestamp); + else return new ReadCoilsResponse(adu, timestamp); + + case QModbusPdu::ReadDiscreteInputs: + if(request) return new ReadDiscreteInputsRequest(adu, timestamp); + else return new ReadDiscreteInputsResponse(adu, timestamp); + + case QModbusPdu::ReadHoldingRegisters: + if(request) return new ReadHoldingRegistersRequest(adu, timestamp); + else return new ReadHoldingRegistersResponse(adu, timestamp); + + case QModbusPdu::ReadInputRegisters: + if(request) return new ReadInputRegistersRequest(adu, timestamp); + else return new ReadInputRegistersResponse(adu, timestamp); + + case QModbusPdu::WriteSingleCoil: + if(request) return new WriteSingleCoilRequest(adu, timestamp); + else return new WriteSingleCoilResponse(adu, timestamp); + + case QModbusPdu::WriteSingleRegister: + if(request) return new WriteSingleRegisterRequest(adu, timestamp); + else return new WriteSingleRegisterResponse(adu, timestamp); + + case QModbusPdu::ReadExceptionStatus: + if(request) return new ReadExceptionStatusRequest(adu, timestamp); + else return new ReadExceptionStatusResponse(adu, timestamp); + + case QModbusPdu::Diagnostics: + if(request) return new DiagnosticsRequest(adu, timestamp); + else return new DiagnosticsResponse(adu, timestamp); + + case QModbusPdu::GetCommEventCounter: + if(request) return new GetCommEventCounterRequest(adu, timestamp); + else return new GetCommEventCounterResponse(adu, timestamp); + + case QModbusPdu::GetCommEventLog: + if(request) return new GetCommEventLogRequest(adu, timestamp); + else return new GetCommEventLogResponse(adu, timestamp); + + case QModbusPdu::WriteMultipleCoils: + if(request) return new WriteMultipleCoilsRequest(adu, timestamp); + else return new WriteMultipleCoilsResponse(adu, timestamp); + + case QModbusPdu::WriteMultipleRegisters: + if(request) return new WriteMultipleRegistersRequest(adu, timestamp); + else return new WriteMultipleRegistersResponse(adu, timestamp); + + case QModbusPdu::ReportServerId: + if(request) return new ReportServerIdRequest(adu, timestamp); + else return new ReportServerIdResponse(adu, timestamp); + + case QModbusPdu::ReadFileRecord: + if(request) return new ReadFileRecordRequest(adu, timestamp); + else return new ReadFileRecordResponse(adu, timestamp); + + case QModbusPdu::WriteFileRecord: + if(request) return new WriteFileRecordRequest(adu, timestamp); + else return new WriteFileRecordResponse(adu, timestamp); + + case QModbusPdu::MaskWriteRegister: + if(request) return new MaskWriteRegisterRequest(adu, timestamp); + else return new MaskWriteRegisterResponse(adu, timestamp); + + case QModbusPdu::ReadWriteMultipleRegisters: + if(request) return new ReadWriteMultipleRegistersRequest(adu, timestamp); + else return new ReadWriteMultipleRegistersResponse(adu, timestamp); + + case QModbusPdu::ReadFifoQueue: + if(request) return new ReadFifoQueueRequest(adu, timestamp); + else return new ReadFifoQueueResponse(adu, timestamp); + + default: + return new ModbusMessage(adu, timestamp, request); + } +} + /// /// \brief ModbusMessage::parse /// \param data -/// \param withDeviceId +/// \param type +/// \param protocol /// \param request /// \return /// -const ModbusMessage* ModbusMessage::parse(const QByteArray& data, bool withDeviceId, bool request) +const ModbusMessage* ModbusMessage::parse(const QByteArray& data, Type type, QModbusAdu::Type protocol, bool request) { - QModbusPdu pdu; - if(withDeviceId) + switch(type) { - pdu.setFunctionCode((QModbusPdu::FunctionCode)data[1]); - if(data.size() > 2) pdu.setData(data.right(data.size() - 2)); + case Adu: + { + QModbusAdu adu(protocol, data); + return create(adu, QDateTime::currentDateTime(), request); + } - return create(pdu, QDateTime::currentDateTime(), data[0], request); - } - else - { - pdu.setFunctionCode((QModbusPdu::FunctionCode)data[0]); - if(data.size() > 1) pdu.setData(data.right(data.size() - 1)); + case Pdu: + { + QModbusPdu pdu; + pdu.setFunctionCode((QModbusPdu::FunctionCode)data[1]); + pdu.setData(data.mid(2, data.size() - 2)); + + return create(pdu, QDateTime::currentDateTime(), data[0], request); + } - return create(pdu, QDateTime::currentDateTime(), 0, request); + default: + return nullptr; } } diff --git a/omodscan/modbusmessages/modbusmessage.h b/omodscan/modbusmessages/modbusmessage.h index 905b096..d3d3f9a 100644 --- a/omodscan/modbusmessages/modbusmessage.h +++ b/omodscan/modbusmessages/modbusmessage.h @@ -2,7 +2,7 @@ #define MODBUSMESSAGE_H #include -#include +#include "qmodbusadu.h" #include "modbuslimits.h" #include "formatutils.h" #include "modbusfunction.h" @@ -14,6 +14,11 @@ class ModbusMessage { public: + enum Type{ + Adu, + Pdu + }; + /// /// \brief ModbusMessage /// \param pdu @@ -21,17 +26,42 @@ class ModbusMessage /// \param deviceId /// \param request /// - ModbusMessage(const QModbusPdu& pdu, const QDateTime& timestamp, int deviceId, bool request) - :_data(pdu.data()) + explicit ModbusMessage(const QModbusPdu& pdu, const QDateTime& timestamp, int deviceId, bool request) + :_type(Type::Pdu) + ,_data(pdu.data()) ,_funcCode(pdu.isException() ? (pdu.functionCode() | QModbusPdu::ExceptionByte) : pdu.functionCode()) ,_exceptionCode(pdu.exceptionCode()) ,_timestamp(timestamp) + ,_transactionId(0) + ,_protocolId(0) + ,_length(0) ,_deviceId(deviceId) ,_request(request) ,_isValid(pdu.isValid()) { } + /// + /// \brief ModbusMessage + /// \param adu + /// \param timestamp + /// \param request + /// + explicit ModbusMessage(const QModbusAdu& adu, const QDateTime& timestamp, bool request) + :_type(Type::Adu) + ,_data(adu.data()) + ,_funcCode(adu.isException() ? (adu.functionCode() | QModbusPdu::ExceptionByte) : adu.functionCode()) + ,_exceptionCode(adu.exceptionCode()) + ,_timestamp(timestamp) + ,_transactionId(adu.transactionId()) + ,_protocolId(adu.protocolId()) + ,_length(adu.length()) + ,_deviceId(adu.serverAddress()) + ,_request(request) + ,_isValid(adu.isValid()) + { + } + /// /// \brief ~ModbusMessage /// @@ -47,14 +77,56 @@ class ModbusMessage /// static const ModbusMessage* create(const QModbusPdu& pdu, const QDateTime& timestamp, int deviceId, bool request); + /// + /// \brief create + /// \param adu + /// \param timestamp + /// \param request + /// \return + /// + static const ModbusMessage* create(const QModbusAdu& adu, const QDateTime& timestamp, bool request); + /// /// \brief parse /// \param data - /// \param withDeviceId + /// \param type + /// \param protocol /// \param request /// \return /// - static const ModbusMessage* parse(const QByteArray& data, bool withDeviceId, bool request); + static const ModbusMessage* parse(const QByteArray& data, Type type, QModbusAdu::Type protocol, bool request); + + /// + /// \brief type + /// \return + /// + Type type() const { + return _type; + } + + /// + /// \brief transactionId + /// \return + /// + int transactionId() const { + return _transactionId; + } + + /// + /// \brief protocolId + /// \return + /// + int protocolId() const { + return _protocolId; + } + + /// + /// \brief length + /// \return + /// + int length() const { + return _length; + } /// /// \brief isValid @@ -96,6 +168,14 @@ class ModbusMessage return ModbusFunction((QModbusPdu::FunctionCode)_funcCode); } + /// + /// \brief functionCode + /// \return + /// + QModbusPdu::FunctionCode functionCode() const { + return (QModbusPdu::FunctionCode)(_funcCode & ~QModbusPdu::ExceptionByte); + } + /// /// \brief isException /// \return @@ -134,20 +214,69 @@ class ModbusMessage /// \brief operator QByteArray /// operator QByteArray() const { - QByteArray data; - data.push_back(_deviceId); - data.push_back(_funcCode); - data.push_back(_data); - return data; + switch(_type) + { + case Adu: + return _data; + + case Pdu: + { + QByteArray data; + data.push_back(_deviceId); + data.push_back(_funcCode); + data.push_back(_data); + return data; + } + } + return QByteArray(); } protected: + int dataSize() const { + switch(_type) + { + case Adu: + return _data.size() - 7; + + case Pdu: + return _data.size(); + } + return 0; + } + + quint8 data(int idx) const { + switch(_type) + { + case Adu: + return _data[7 + idx]; + + case Pdu: + return _data[idx]; + } + return 0; + } + + QByteArray slice(int idx, int len = -1) const { + switch(_type) + { + case Adu: + return _data.mid(idx + 7, len); + + case Pdu: + return _data.mid(idx, len); + } + return 0; + } + +private: + const Type _type; const QByteArray _data; const quint8 _funcCode; const quint8 _exceptionCode; - -private: const QDateTime _timestamp; + const int _transactionId; + const int _protocolId; + const int _length; const int _deviceId; const bool _request; const bool _isValid; diff --git a/omodscan/modbusmessages/readcoils.h b/omodscan/modbusmessages/readcoils.h index 4c03a48..a06353a 100644 --- a/omodscan/modbusmessages/readcoils.h +++ b/omodscan/modbusmessages/readcoils.h @@ -19,7 +19,18 @@ class ReadCoilsRequest : public ModbusMessage ReadCoilsRequest(const QModbusPdu& pdu, const QDateTime& timestamp, int deviceId) : ModbusMessage(pdu, timestamp, deviceId, true) { - Q_ASSERT((_funcCode & ~QModbusPdu::ExceptionByte) == QModbusPdu::ReadCoils); + Q_ASSERT(functionCode() == QModbusPdu::ReadCoils); + } + + /// + /// \brief ReadCoilsRequest + /// \param adu + /// \param timestamp + /// + ReadCoilsRequest(const QModbusAdu& adu, const QDateTime& timestamp) + : ModbusMessage(adu, timestamp, true) + { + Q_ASSERT(functionCode() == QModbusPdu::ReadCoils); } /// @@ -27,7 +38,7 @@ class ReadCoilsRequest : public ModbusMessage /// \return /// bool isValid() const override { - return ModbusMessage::isValid() && _data.size() == 4; + return ModbusMessage::isValid() && dataSize() == 4; } /// @@ -35,7 +46,7 @@ class ReadCoilsRequest : public ModbusMessage /// \return /// quint16 startAddress() const { - return makeWord(_data[1], _data[0], ByteOrder::LittleEndian); + return makeWord(data(1), data(0), ByteOrder::LittleEndian); } /// @@ -43,7 +54,7 @@ class ReadCoilsRequest : public ModbusMessage /// \return /// quint16 length() const { - return makeWord(_data[3], _data[2], ByteOrder::LittleEndian); + return makeWord(data(3), data(2), ByteOrder::LittleEndian); } }; @@ -62,7 +73,18 @@ class ReadCoilsResponse : public ModbusMessage ReadCoilsResponse(const QModbusPdu& pdu, const QDateTime& timestamp, int deviceId) :ModbusMessage(pdu, timestamp, deviceId, false) { - Q_ASSERT((_funcCode & ~QModbusPdu::ExceptionByte) == QModbusPdu::ReadCoils); + Q_ASSERT(functionCode() == QModbusPdu::ReadCoils); + } + + /// + /// \brief ReadCoilsResponse + /// \param adu + /// \param timestamp + /// + ReadCoilsResponse(const QModbusAdu& adu, const QDateTime& timestamp) + : ModbusMessage(adu, timestamp, true) + { + Q_ASSERT(functionCode() == QModbusPdu::ReadCoils); } /// @@ -70,7 +92,7 @@ class ReadCoilsResponse : public ModbusMessage /// \return /// bool isValid() const override { - return ModbusMessage::isValid() && _data.size() > 1; + return ModbusMessage::isValid() && dataSize() > 1; } /// @@ -78,7 +100,7 @@ class ReadCoilsResponse : public ModbusMessage /// \return /// quint8 byteCount() const { - return _data[0]; + return data(0); } /// @@ -86,7 +108,7 @@ class ReadCoilsResponse : public ModbusMessage /// \return /// QByteArray coilStatus() const { - return _data.right(_data.size() - 1); + return slice(1); } }; diff --git a/omodscan/modbusmessages/readdiscreteinputs.h b/omodscan/modbusmessages/readdiscreteinputs.h index 974cf1d..87f426f 100644 --- a/omodscan/modbusmessages/readdiscreteinputs.h +++ b/omodscan/modbusmessages/readdiscreteinputs.h @@ -18,7 +18,18 @@ class ReadDiscreteInputsRequest : public ModbusMessage ReadDiscreteInputsRequest(const QModbusPdu& pdu, const QDateTime& timestamp, int deviceId) : ModbusMessage(pdu, timestamp, deviceId, true) { - Q_ASSERT((_funcCode & ~QModbusPdu::ExceptionByte) == QModbusPdu::ReadDiscreteInputs); + Q_ASSERT(functionCode() == QModbusPdu::ReadDiscreteInputs); + } + + /// + /// \brief ReadDiscreteInputsRequest + /// \param adu + /// \param timestamp + /// + ReadDiscreteInputsRequest(const QModbusAdu& adu, const QDateTime& timestamp) + : ModbusMessage(adu, timestamp, true) + { + Q_ASSERT(functionCode() == QModbusPdu::ReadDiscreteInputs); } /// @@ -26,7 +37,7 @@ class ReadDiscreteInputsRequest : public ModbusMessage /// \return /// bool isValid() const override { - return ModbusMessage::isValid() && _data.size() == 4; + return ModbusMessage::isValid() && dataSize() == 4; } /// @@ -34,7 +45,7 @@ class ReadDiscreteInputsRequest : public ModbusMessage /// \return /// quint16 startAddress() const { - return makeWord(_data[1], _data[0], ByteOrder::LittleEndian); + return makeWord(data(1), data(0), ByteOrder::LittleEndian); } /// @@ -42,7 +53,7 @@ class ReadDiscreteInputsRequest : public ModbusMessage /// \return /// quint16 length() const { - return makeWord(_data[3], _data[2], ByteOrder::LittleEndian); + return makeWord(data(3), data(2), ByteOrder::LittleEndian); } }; @@ -61,7 +72,18 @@ class ReadDiscreteInputsResponse : public ModbusMessage ReadDiscreteInputsResponse(const QModbusPdu& pdu, const QDateTime& timestamp, int deviceId) :ModbusMessage(pdu, timestamp, deviceId, false) { - Q_ASSERT((_funcCode & ~QModbusPdu::ExceptionByte) == QModbusPdu::ReadDiscreteInputs); + Q_ASSERT(functionCode() == QModbusPdu::ReadDiscreteInputs); + } + + /// + /// \brief ReadDiscreteInputsResponse + /// \param adu + /// \param timestamp + /// + ReadDiscreteInputsResponse(const QModbusAdu& adu, const QDateTime& timestamp) + : ModbusMessage(adu, timestamp, true) + { + Q_ASSERT(functionCode() == QModbusPdu::ReadDiscreteInputs); } /// @@ -69,7 +91,7 @@ class ReadDiscreteInputsResponse : public ModbusMessage /// \return /// bool isValid() const override { - return ModbusMessage::isValid() && _data.size() > 1; + return ModbusMessage::isValid() && dataSize() > 1; } /// @@ -77,7 +99,7 @@ class ReadDiscreteInputsResponse : public ModbusMessage /// \return /// quint8 byteCount() const { - return _data[0]; + return data(0); } /// @@ -85,7 +107,7 @@ class ReadDiscreteInputsResponse : public ModbusMessage /// \return /// QByteArray inputStatus() const { - return _data.right(_data.size() - 1); + return slice(1); } }; diff --git a/omodscan/modbusmessages/readexceptionstatus.h b/omodscan/modbusmessages/readexceptionstatus.h index 90fb570..210f98a 100644 --- a/omodscan/modbusmessages/readexceptionstatus.h +++ b/omodscan/modbusmessages/readexceptionstatus.h @@ -18,7 +18,18 @@ class ReadExceptionStatusRequest : public ModbusMessage ReadExceptionStatusRequest(const QModbusPdu& pdu, const QDateTime& timestamp, int deviceId) : ModbusMessage(pdu, timestamp, deviceId, true) { - Q_ASSERT((_funcCode & ~QModbusPdu::ExceptionByte) == QModbusPdu::ReadExceptionStatus); + Q_ASSERT(functionCode() == QModbusPdu::ReadExceptionStatus); + } + + /// + /// \brief ReadExceptionStatusRequest + /// \param adu + /// \param timestamp + /// + ReadExceptionStatusRequest(const QModbusAdu& adu, const QDateTime& timestamp) + : ModbusMessage(adu, timestamp, true) + { + Q_ASSERT(functionCode() == QModbusPdu::ReadExceptionStatus); } }; @@ -37,7 +48,18 @@ class ReadExceptionStatusResponse : public ModbusMessage ReadExceptionStatusResponse(const QModbusPdu& pdu, const QDateTime& timestamp, int deviceId) :ModbusMessage(pdu, timestamp, deviceId, false) { - Q_ASSERT((_funcCode & ~QModbusPdu::ExceptionByte) == QModbusPdu::ReadExceptionStatus); + Q_ASSERT(functionCode() == QModbusPdu::ReadExceptionStatus); + } + + /// + /// \brief ReadExceptionStatusResponse + /// \param adu + /// \param timestamp + /// + ReadExceptionStatusResponse(const QModbusAdu& adu, const QDateTime& timestamp) + : ModbusMessage(adu, timestamp, true) + { + Q_ASSERT(functionCode() == QModbusPdu::ReadExceptionStatus); } /// @@ -45,7 +67,7 @@ class ReadExceptionStatusResponse : public ModbusMessage /// \return /// bool isValid() const override { - return ModbusMessage::isValid() && _data.size() == 1; + return ModbusMessage::isValid() && dataSize() == 1; } /// @@ -53,7 +75,7 @@ class ReadExceptionStatusResponse : public ModbusMessage /// \return /// quint8 outputData() const { - return _data[0]; + return data(0); } }; diff --git a/omodscan/modbusmessages/readfifoqueue.h b/omodscan/modbusmessages/readfifoqueue.h index c4bf519..001431b 100644 --- a/omodscan/modbusmessages/readfifoqueue.h +++ b/omodscan/modbusmessages/readfifoqueue.h @@ -18,7 +18,18 @@ class ReadFifoQueueRequest : public ModbusMessage ReadFifoQueueRequest(const QModbusPdu& pdu, const QDateTime& timestamp, int deviceId) : ModbusMessage(pdu, timestamp, deviceId, true) { - Q_ASSERT((_funcCode & ~QModbusPdu::ExceptionByte) == QModbusPdu::ReadFifoQueue); + Q_ASSERT(functionCode() == QModbusPdu::ReadFifoQueue); + } + + /// + /// \brief ReadFifoQueueRequest + /// \param adu + /// \param timestamp + /// + ReadFifoQueueRequest(const QModbusAdu& adu, const QDateTime& timestamp) + : ModbusMessage(adu, timestamp, true) + { + Q_ASSERT(functionCode() == QModbusPdu::ReadFifoQueue); } /// @@ -26,7 +37,7 @@ class ReadFifoQueueRequest : public ModbusMessage /// \return /// bool isValid() const override { - return ModbusMessage::isValid() && _data.size() == 2; + return ModbusMessage::isValid() && dataSize() == 2; } /// @@ -34,7 +45,7 @@ class ReadFifoQueueRequest : public ModbusMessage /// \return /// quint16 fifoAddress() const { - return makeWord(_data[1], _data[0], ByteOrder::LittleEndian); + return makeWord(data(1), data(0), ByteOrder::LittleEndian); } }; @@ -53,7 +64,18 @@ class ReadFifoQueueResponse : public ModbusMessage ReadFifoQueueResponse(const QModbusPdu& pdu, const QDateTime& timestamp, int deviceId) :ModbusMessage(pdu, timestamp, deviceId, false) { - Q_ASSERT((_funcCode & ~QModbusPdu::ExceptionByte) == QModbusPdu::ReadFifoQueue); + Q_ASSERT(functionCode() == QModbusPdu::ReadFifoQueue); + } + + /// + /// \brief ReadFifoQueueResponse + /// \param adu + /// \param timestamp + /// + ReadFifoQueueResponse(const QModbusAdu& adu, const QDateTime& timestamp) + : ModbusMessage(adu, timestamp, true) + { + Q_ASSERT(functionCode() == QModbusPdu::ReadFifoQueue); } /// @@ -61,7 +83,7 @@ class ReadFifoQueueResponse : public ModbusMessage /// \return /// bool isValid() const override { - return ModbusMessage::isValid() && _data.size() > 5; + return ModbusMessage::isValid() && dataSize() > 5; } /// @@ -69,7 +91,7 @@ class ReadFifoQueueResponse : public ModbusMessage /// \return /// quint16 byteCount() const { - return makeWord(_data[1], _data[0], ByteOrder::LittleEndian); + return makeWord(data(1), data(0), ByteOrder::LittleEndian); } /// @@ -77,7 +99,7 @@ class ReadFifoQueueResponse : public ModbusMessage /// \return /// quint16 fifoCount() const { - return makeWord(_data[3], _data[2], ByteOrder::LittleEndian); + return makeWord(data(3), data(2), ByteOrder::LittleEndian); } /// @@ -85,7 +107,7 @@ class ReadFifoQueueResponse : public ModbusMessage /// \return /// QByteArray fifoValue() const { - return _data.right(_data.size() - 4); + return slice(4); } }; diff --git a/omodscan/modbusmessages/readfilerecord.h b/omodscan/modbusmessages/readfilerecord.h index feab598..cc510e7 100644 --- a/omodscan/modbusmessages/readfilerecord.h +++ b/omodscan/modbusmessages/readfilerecord.h @@ -18,7 +18,18 @@ class ReadFileRecordRequest : public ModbusMessage ReadFileRecordRequest(const QModbusPdu& pdu, const QDateTime& timestamp, int deviceId) : ModbusMessage(pdu, timestamp, deviceId, true) { - Q_ASSERT((_funcCode & ~QModbusPdu::ExceptionByte) == QModbusPdu::ReadFileRecord); + Q_ASSERT(functionCode() == QModbusPdu::ReadFileRecord); + } + + /// + /// \brief ReadFileRecordRequest + /// \param adu + /// \param timestamp + /// + ReadFileRecordRequest(const QModbusAdu& adu, const QDateTime& timestamp) + : ModbusMessage(adu, timestamp, true) + { + Q_ASSERT(functionCode() == QModbusPdu::ReadFileRecord); } /// @@ -26,7 +37,7 @@ class ReadFileRecordRequest : public ModbusMessage /// \return /// bool isValid() const override { - return ModbusMessage::isValid() && _data.size() > 1; + return ModbusMessage::isValid() && dataSize() > 1; } /// @@ -34,7 +45,7 @@ class ReadFileRecordRequest : public ModbusMessage /// \return /// quint8 byteCount() const { - return _data[0]; + return ModbusMessage::data(0); } /// @@ -42,7 +53,7 @@ class ReadFileRecordRequest : public ModbusMessage /// \return /// QByteArray data() const { - return _data.right(_data.size() - 1); + return slice(1); } }; @@ -61,7 +72,18 @@ class ReadFileRecordResponse : public ModbusMessage ReadFileRecordResponse(const QModbusPdu& pdu, const QDateTime& timestamp, int deviceId) :ModbusMessage(pdu, timestamp, deviceId, false) { - Q_ASSERT((_funcCode & ~QModbusPdu::ExceptionByte) == QModbusPdu::ReadFileRecord); + Q_ASSERT(functionCode() == QModbusPdu::ReadFileRecord); + } + + /// + /// \brief ReadFileRecordResponse + /// \param adu + /// \param timestamp + /// + ReadFileRecordResponse(const QModbusAdu& adu, const QDateTime& timestamp) + : ModbusMessage(adu, timestamp, true) + { + Q_ASSERT(functionCode() == QModbusPdu::ReadFileRecord); } /// @@ -69,7 +91,7 @@ class ReadFileRecordResponse : public ModbusMessage /// \return /// bool isValid() const override { - return ModbusMessage::isValid() && _data.size() > 1; + return ModbusMessage::isValid() && dataSize() > 1; } /// @@ -77,7 +99,7 @@ class ReadFileRecordResponse : public ModbusMessage /// \return /// quint8 byteCount() const { - return _data[0]; + return ModbusMessage::data(0); } /// @@ -85,7 +107,7 @@ class ReadFileRecordResponse : public ModbusMessage /// \return /// QByteArray data() const { - return _data.right(_data.size() - 1); + return slice(1); } }; diff --git a/omodscan/modbusmessages/readholdingregisters.h b/omodscan/modbusmessages/readholdingregisters.h index d62a048..4478f0b 100644 --- a/omodscan/modbusmessages/readholdingregisters.h +++ b/omodscan/modbusmessages/readholdingregisters.h @@ -18,7 +18,18 @@ class ReadHoldingRegistersRequest : public ModbusMessage ReadHoldingRegistersRequest(const QModbusPdu& pdu, const QDateTime& timestamp, int deviceId) : ModbusMessage(pdu, timestamp, deviceId, true) { - Q_ASSERT((_funcCode & ~QModbusPdu::ExceptionByte) == QModbusPdu::ReadHoldingRegisters); + Q_ASSERT(functionCode() == QModbusPdu::ReadHoldingRegisters); + } + + /// + /// \brief ReadHoldingRegistersRequest + /// \param adu + /// \param timestamp + /// + ReadHoldingRegistersRequest(const QModbusAdu& adu, const QDateTime& timestamp) + : ModbusMessage(adu, timestamp, true) + { + Q_ASSERT(functionCode() == QModbusPdu::ReadHoldingRegisters); } /// @@ -26,7 +37,7 @@ class ReadHoldingRegistersRequest : public ModbusMessage /// \return /// bool isValid() const override { - return ModbusMessage::isValid() && _data.size() == 4; + return ModbusMessage::isValid() && dataSize() == 4; } /// @@ -34,7 +45,7 @@ class ReadHoldingRegistersRequest : public ModbusMessage /// \return /// quint16 startAddress() const { - return makeWord(_data[1], _data[0], ByteOrder::LittleEndian); + return makeWord(data(1), data(0), ByteOrder::LittleEndian); } /// @@ -42,7 +53,7 @@ class ReadHoldingRegistersRequest : public ModbusMessage /// \return /// quint16 length() const { - return makeWord(_data[3], _data[2], ByteOrder::LittleEndian); + return makeWord(data(3), data(2), ByteOrder::LittleEndian); } }; @@ -61,7 +72,18 @@ class ReadHoldingRegistersResponse : public ModbusMessage ReadHoldingRegistersResponse(const QModbusPdu& pdu, const QDateTime& timestamp, int deviceId) :ModbusMessage(pdu, timestamp, deviceId, false) { - Q_ASSERT((_funcCode & ~QModbusPdu::ExceptionByte) == QModbusPdu::ReadHoldingRegisters); + Q_ASSERT(functionCode() == QModbusPdu::ReadHoldingRegisters); + } + + /// + /// \brief ReadHoldingRegistersResponse + /// \param adu + /// \param timestamp + /// + ReadHoldingRegistersResponse(const QModbusAdu& adu, const QDateTime& timestamp) + : ModbusMessage(adu, timestamp, true) + { + Q_ASSERT(functionCode() == QModbusPdu::ReadHoldingRegisters); } /// @@ -69,7 +91,7 @@ class ReadHoldingRegistersResponse : public ModbusMessage /// \return /// bool isValid() const override { - return ModbusMessage::isValid() && _data.size() > 1; + return ModbusMessage::isValid() && dataSize() > 1; } /// @@ -77,7 +99,7 @@ class ReadHoldingRegistersResponse : public ModbusMessage /// \return /// quint8 byteCount() const { - return _data[0]; + return data(0); } /// @@ -85,7 +107,7 @@ class ReadHoldingRegistersResponse : public ModbusMessage /// \return /// QByteArray registerValue() const { - return _data.right(_data.size() - 1); + return slice(1); } }; diff --git a/omodscan/modbusmessages/readinputregisters.h b/omodscan/modbusmessages/readinputregisters.h index 7d5ab4b..a637303 100644 --- a/omodscan/modbusmessages/readinputregisters.h +++ b/omodscan/modbusmessages/readinputregisters.h @@ -18,7 +18,18 @@ class ReadInputRegistersRequest : public ModbusMessage ReadInputRegistersRequest(const QModbusPdu& pdu, const QDateTime& timestamp, int deviceId) : ModbusMessage(pdu, timestamp, deviceId, true) { - Q_ASSERT((_funcCode & ~QModbusPdu::ExceptionByte) == QModbusPdu::ReadInputRegisters); + Q_ASSERT(functionCode() == QModbusPdu::ReadInputRegisters); + } + + /// + /// \brief ReadInputRegistersRequest + /// \param adu + /// \param timestamp + /// + ReadInputRegistersRequest(const QModbusAdu& adu, const QDateTime& timestamp) + : ModbusMessage(adu, timestamp, true) + { + Q_ASSERT(functionCode() == QModbusPdu::ReadInputRegisters); } /// @@ -26,7 +37,7 @@ class ReadInputRegistersRequest : public ModbusMessage /// \return /// bool isValid() const override { - return ModbusMessage::isValid() && _data.size() == 4; + return ModbusMessage::isValid() && dataSize() == 4; } /// @@ -34,7 +45,7 @@ class ReadInputRegistersRequest : public ModbusMessage /// \return /// quint16 startAddress() const { - return makeWord(_data[1], _data[0], ByteOrder::LittleEndian); + return makeWord(data(1), data(0), ByteOrder::LittleEndian); } /// @@ -42,7 +53,7 @@ class ReadInputRegistersRequest : public ModbusMessage /// \return /// quint16 length() const { - return makeWord(_data[3], _data[2], ByteOrder::LittleEndian); + return makeWord(data(3), data(2), ByteOrder::LittleEndian); } }; @@ -61,7 +72,18 @@ class ReadInputRegistersResponse : public ModbusMessage ReadInputRegistersResponse(const QModbusPdu& pdu, const QDateTime& timestamp, int deviceId) :ModbusMessage(pdu, timestamp, deviceId, false) { - Q_ASSERT((_funcCode & ~QModbusPdu::ExceptionByte) == QModbusPdu::ReadInputRegisters); + Q_ASSERT(functionCode() == QModbusPdu::ReadInputRegisters); + } + + /// + /// \brief ReadInputRegistersResponse + /// \param adu + /// \param timestamp + /// + ReadInputRegistersResponse(const QModbusAdu& adu, const QDateTime& timestamp) + : ModbusMessage(adu, timestamp, true) + { + Q_ASSERT(functionCode() == QModbusPdu::ReadInputRegisters); } /// @@ -69,7 +91,7 @@ class ReadInputRegistersResponse : public ModbusMessage /// \return /// bool isValid() const override { - return ModbusMessage::isValid() && _data.size() > 1; + return ModbusMessage::isValid() && dataSize() > 1; } /// @@ -77,7 +99,7 @@ class ReadInputRegistersResponse : public ModbusMessage /// \return /// quint8 byteCount() const { - return _data[0]; + return data(0); } /// @@ -85,7 +107,7 @@ class ReadInputRegistersResponse : public ModbusMessage /// \return /// QByteArray registerValue() const { - return _data.right(_data.size() - 1); + return slice(1); } }; diff --git a/omodscan/modbusmessages/readwritemultipleregisters.h b/omodscan/modbusmessages/readwritemultipleregisters.h index 3a5954c..7df148f 100644 --- a/omodscan/modbusmessages/readwritemultipleregisters.h +++ b/omodscan/modbusmessages/readwritemultipleregisters.h @@ -18,7 +18,18 @@ class ReadWriteMultipleRegistersRequest : public ModbusMessage ReadWriteMultipleRegistersRequest(const QModbusPdu& pdu, const QDateTime& timestamp, int deviceId) : ModbusMessage(pdu, timestamp, deviceId, true) { - Q_ASSERT((_funcCode & ~QModbusPdu::ExceptionByte) == QModbusPdu::ReadWriteMultipleRegisters); + Q_ASSERT(functionCode() == QModbusPdu::ReadWriteMultipleRegisters); + } + + /// + /// \brief ReadWriteMultipleRegistersRequest + /// \param adu + /// \param timestamp + /// + ReadWriteMultipleRegistersRequest(const QModbusAdu& adu, const QDateTime& timestamp) + : ModbusMessage(adu, timestamp, true) + { + Q_ASSERT(functionCode() == QModbusPdu::ReadWriteMultipleRegisters); } /// @@ -26,7 +37,7 @@ class ReadWriteMultipleRegistersRequest : public ModbusMessage /// \return /// bool isValid() const override { - return ModbusMessage::isValid() && _data.size() > 9; + return ModbusMessage::isValid() && dataSize() > 9; } /// @@ -34,7 +45,7 @@ class ReadWriteMultipleRegistersRequest : public ModbusMessage /// \return /// quint16 readStartAddress() const { - return makeWord(_data[1], _data[0], ByteOrder::LittleEndian); + return makeWord(data(1), data(0), ByteOrder::LittleEndian); } /// @@ -42,7 +53,7 @@ class ReadWriteMultipleRegistersRequest : public ModbusMessage /// \return /// quint16 readLength() const { - return makeWord(_data[3], _data[2], ByteOrder::LittleEndian); + return makeWord(data(3), data(2), ByteOrder::LittleEndian); } /// @@ -50,7 +61,7 @@ class ReadWriteMultipleRegistersRequest : public ModbusMessage /// \return /// quint16 writeStartAddress() const { - return makeWord(_data[5], _data[4], ByteOrder::LittleEndian); + return makeWord(data(5), data(4), ByteOrder::LittleEndian); } /// @@ -58,7 +69,7 @@ class ReadWriteMultipleRegistersRequest : public ModbusMessage /// \return /// quint16 writeLength() const { - return makeWord(_data[7], _data[6], ByteOrder::LittleEndian); + return makeWord(data(7), data(6), ByteOrder::LittleEndian); } /// @@ -66,7 +77,7 @@ class ReadWriteMultipleRegistersRequest : public ModbusMessage /// \return /// quint8 writeByteCount() const { - return _data[8]; + return data(8); } /// @@ -74,7 +85,7 @@ class ReadWriteMultipleRegistersRequest : public ModbusMessage /// \return /// QByteArray writeValues() const { - return _data.right(_data.size() - 9); + return slice(9); } }; @@ -93,7 +104,18 @@ class ReadWriteMultipleRegistersResponse : public ModbusMessage ReadWriteMultipleRegistersResponse(const QModbusPdu& pdu, const QDateTime& timestamp, int deviceId) :ModbusMessage(pdu, timestamp, deviceId, false) { - Q_ASSERT((_funcCode & ~QModbusPdu::ExceptionByte) == QModbusPdu::ReadWriteMultipleRegisters); + Q_ASSERT(functionCode() == QModbusPdu::ReadWriteMultipleRegisters); + } + + /// + /// \brief ReadWriteMultipleRegistersResponse + /// \param adu + /// \param timestamp + /// + ReadWriteMultipleRegistersResponse(const QModbusAdu& adu, const QDateTime& timestamp) + : ModbusMessage(adu, timestamp, true) + { + Q_ASSERT(functionCode() == QModbusPdu::ReadWriteMultipleRegisters); } /// @@ -101,7 +123,7 @@ class ReadWriteMultipleRegistersResponse : public ModbusMessage /// \return /// bool isValid() const override { - return ModbusMessage::isValid() && _data.size() > 1; + return ModbusMessage::isValid() && dataSize() > 1; } /// @@ -109,7 +131,7 @@ class ReadWriteMultipleRegistersResponse : public ModbusMessage /// \return /// quint8 byteCount() const { - return _data[0]; + return data(0); } /// @@ -117,7 +139,7 @@ class ReadWriteMultipleRegistersResponse : public ModbusMessage /// \return /// QByteArray values() const { - return _data.right(_data.size() - 1); + return slice(1); } }; diff --git a/omodscan/modbusmessages/reportserverid.h b/omodscan/modbusmessages/reportserverid.h index 49869da..9b23b47 100644 --- a/omodscan/modbusmessages/reportserverid.h +++ b/omodscan/modbusmessages/reportserverid.h @@ -18,7 +18,18 @@ class ReportServerIdRequest : public ModbusMessage ReportServerIdRequest(const QModbusPdu& pdu, const QDateTime& timestamp, int deviceId) : ModbusMessage(pdu, timestamp, deviceId, true) { - Q_ASSERT((_funcCode & ~QModbusPdu::ExceptionByte) == QModbusPdu::ReportServerId); + Q_ASSERT(functionCode() == QModbusPdu::ReportServerId); + } + + /// + /// \brief ReportServerIdRequest + /// \param adu + /// \param timestamp + /// + ReportServerIdRequest(const QModbusAdu& adu, const QDateTime& timestamp) + : ModbusMessage(adu, timestamp, true) + { + Q_ASSERT(functionCode() == QModbusPdu::ReportServerId); } }; @@ -37,7 +48,18 @@ class ReportServerIdResponse : public ModbusMessage ReportServerIdResponse(const QModbusPdu& pdu, const QDateTime& timestamp, int deviceId) :ModbusMessage(pdu, timestamp, deviceId, false) { - Q_ASSERT((_funcCode & ~QModbusPdu::ExceptionByte) == QModbusPdu::ReportServerId); + Q_ASSERT(functionCode() == QModbusPdu::ReportServerId); + } + + /// + /// \brief ReportServerIdResponse + /// \param adu + /// \param timestamp + /// + ReportServerIdResponse(const QModbusAdu& adu, const QDateTime& timestamp) + : ModbusMessage(adu, timestamp, true) + { + Q_ASSERT(functionCode() == QModbusPdu::ReportServerId); } /// @@ -45,7 +67,7 @@ class ReportServerIdResponse : public ModbusMessage /// \return /// bool isValid() const override { - return ModbusMessage::isValid() && _data.size() > 1; + return ModbusMessage::isValid() && dataSize() > 1; } /// @@ -53,7 +75,7 @@ class ReportServerIdResponse : public ModbusMessage /// \return /// quint8 byteCount() const { - return _data[0]; + return ModbusMessage::data(0); } /// @@ -61,7 +83,7 @@ class ReportServerIdResponse : public ModbusMessage /// \return /// QByteArray data() const { - return _data.right(_data.size() - 1); + return slice(1); } }; diff --git a/omodscan/modbusmessages/writefilerecord.h b/omodscan/modbusmessages/writefilerecord.h index 36f74e7..d0661c4 100644 --- a/omodscan/modbusmessages/writefilerecord.h +++ b/omodscan/modbusmessages/writefilerecord.h @@ -18,7 +18,18 @@ class WriteFileRecordRequest : public ModbusMessage WriteFileRecordRequest(const QModbusPdu& pdu, const QDateTime& timestamp, int deviceId) : ModbusMessage(pdu, timestamp, deviceId, true) { - Q_ASSERT((_funcCode & ~QModbusPdu::ExceptionByte) == QModbusPdu::WriteFileRecord); + Q_ASSERT(functionCode() == QModbusPdu::WriteFileRecord); + } + + /// + /// \brief WriteFileRecordRequest + /// \param adu + /// \param timestamp + /// + WriteFileRecordRequest(const QModbusAdu& adu, const QDateTime& timestamp) + : ModbusMessage(adu, timestamp, true) + { + Q_ASSERT(functionCode() == QModbusPdu::WriteFileRecord); } /// @@ -26,7 +37,7 @@ class WriteFileRecordRequest : public ModbusMessage /// \return /// bool isValid() const override { - return ModbusMessage::isValid() && _data.size() > 1; + return ModbusMessage::isValid() && dataSize() > 1; } /// @@ -34,7 +45,7 @@ class WriteFileRecordRequest : public ModbusMessage /// \return /// quint8 length() const { - return _data[0]; + return ModbusMessage::data(0); } /// @@ -42,7 +53,7 @@ class WriteFileRecordRequest : public ModbusMessage /// \return /// QByteArray data() const { - return _data.right(_data.size() - 1); + return slice(1); } }; @@ -61,7 +72,18 @@ class WriteFileRecordResponse : public ModbusMessage WriteFileRecordResponse(const QModbusPdu& pdu, const QDateTime& timestamp, int deviceId) :ModbusMessage(pdu, timestamp, deviceId, false) { - Q_ASSERT((_funcCode & ~QModbusPdu::ExceptionByte) == QModbusPdu::WriteFileRecord); + Q_ASSERT(functionCode() == QModbusPdu::WriteFileRecord); + } + + /// + /// \brief WriteFileRecordResponse + /// \param adu + /// \param timestamp + /// + WriteFileRecordResponse(const QModbusAdu& adu, const QDateTime& timestamp) + : ModbusMessage(adu, timestamp, true) + { + Q_ASSERT(functionCode() == QModbusPdu::WriteFileRecord); } /// @@ -69,7 +91,7 @@ class WriteFileRecordResponse : public ModbusMessage /// \return /// bool isValid() const override { - return ModbusMessage::isValid() && _data.size() > 1; + return ModbusMessage::isValid() && dataSize() > 1; } /// @@ -77,7 +99,7 @@ class WriteFileRecordResponse : public ModbusMessage /// \return /// quint8 length() const { - return _data[0]; + return ModbusMessage::data(0); } /// @@ -85,7 +107,7 @@ class WriteFileRecordResponse : public ModbusMessage /// \return /// QByteArray data() const { - return _data.right(_data.size() - 1); + return slice(1); } }; diff --git a/omodscan/modbusmessages/writemultiplecoils.h b/omodscan/modbusmessages/writemultiplecoils.h index f621d4a..5e64d5f 100644 --- a/omodscan/modbusmessages/writemultiplecoils.h +++ b/omodscan/modbusmessages/writemultiplecoils.h @@ -18,7 +18,18 @@ class WriteMultipleCoilsRequest : public ModbusMessage WriteMultipleCoilsRequest(const QModbusPdu& pdu, const QDateTime& timestamp, int deviceId) : ModbusMessage(pdu, timestamp, deviceId, true) { - Q_ASSERT((_funcCode & ~QModbusPdu::ExceptionByte) == QModbusPdu::WriteMultipleCoils); + Q_ASSERT(functionCode() == QModbusPdu::WriteMultipleCoils); + } + + /// + /// \brief WriteMultipleCoilsRequest + /// \param adu + /// \param timestamp + /// + WriteMultipleCoilsRequest(const QModbusAdu& adu, const QDateTime& timestamp) + : ModbusMessage(adu, timestamp, true) + { + Q_ASSERT(functionCode() == QModbusPdu::WriteMultipleCoils); } /// @@ -26,7 +37,7 @@ class WriteMultipleCoilsRequest : public ModbusMessage /// \return /// bool isValid() const override { - return ModbusMessage::isValid() && _data.size() > 5; + return ModbusMessage::isValid() && dataSize() > 5; } /// @@ -34,7 +45,7 @@ class WriteMultipleCoilsRequest : public ModbusMessage /// \return /// quint16 startAddress() const { - return makeWord(_data[1], _data[0], ByteOrder::LittleEndian); + return makeWord(data(1), data(0), ByteOrder::LittleEndian); } /// @@ -42,7 +53,7 @@ class WriteMultipleCoilsRequest : public ModbusMessage /// \return /// quint16 quantity() const { - return makeWord(_data[3], _data[2], ByteOrder::LittleEndian); + return makeWord(data(3), data(2), ByteOrder::LittleEndian); } /// @@ -50,7 +61,7 @@ class WriteMultipleCoilsRequest : public ModbusMessage /// \return /// quint8 byteCount() const { - return _data[4]; + return data(4); } /// @@ -58,7 +69,7 @@ class WriteMultipleCoilsRequest : public ModbusMessage /// \return /// QByteArray values() const { - return _data.right(_data.size() - 5); + return slice(5); } }; @@ -77,7 +88,18 @@ class WriteMultipleCoilsResponse : public ModbusMessage WriteMultipleCoilsResponse(const QModbusPdu& pdu, const QDateTime& timestamp, int deviceId) :ModbusMessage(pdu, timestamp, deviceId, false) { - Q_ASSERT((_funcCode & ~QModbusPdu::ExceptionByte) == QModbusPdu::WriteMultipleCoils); + Q_ASSERT(functionCode() == QModbusPdu::WriteMultipleCoils); + } + + /// + /// \brief WriteMultipleCoilsResponse + /// \param adu + /// \param timestamp + /// + WriteMultipleCoilsResponse(const QModbusAdu& adu, const QDateTime& timestamp) + : ModbusMessage(adu, timestamp, true) + { + Q_ASSERT(functionCode() == QModbusPdu::WriteMultipleCoils); } /// @@ -85,7 +107,7 @@ class WriteMultipleCoilsResponse : public ModbusMessage /// \return /// bool isValid() const override { - return ModbusMessage::isValid() && _data.size() == 4; + return ModbusMessage::isValid() && dataSize() == 4; } /// @@ -93,7 +115,7 @@ class WriteMultipleCoilsResponse : public ModbusMessage /// \return /// quint16 startAddress() const { - return makeWord(_data[1], _data[0], ByteOrder::LittleEndian); + return makeWord(data(1), data(0), ByteOrder::LittleEndian); } /// @@ -101,7 +123,7 @@ class WriteMultipleCoilsResponse : public ModbusMessage /// \return /// quint16 quantity() const { - return makeWord(_data[3], _data[2], ByteOrder::LittleEndian); + return makeWord(data(3), data(2), ByteOrder::LittleEndian); } }; diff --git a/omodscan/modbusmessages/writemultipleregisters.h b/omodscan/modbusmessages/writemultipleregisters.h index 5a64870..f4e5ba4 100644 --- a/omodscan/modbusmessages/writemultipleregisters.h +++ b/omodscan/modbusmessages/writemultipleregisters.h @@ -18,7 +18,18 @@ class WriteMultipleRegistersRequest : public ModbusMessage WriteMultipleRegistersRequest(const QModbusPdu& pdu, const QDateTime& timestamp, int deviceId) : ModbusMessage(pdu, timestamp, deviceId, true) { - Q_ASSERT((_funcCode & ~QModbusPdu::ExceptionByte) == QModbusPdu::WriteMultipleRegisters); + Q_ASSERT(functionCode() == QModbusPdu::WriteMultipleRegisters); + } + + /// + /// \brief WriteMultipleRegistersRequest + /// \param adu + /// \param timestamp + /// + WriteMultipleRegistersRequest(const QModbusAdu& adu, const QDateTime& timestamp) + : ModbusMessage(adu, timestamp, true) + { + Q_ASSERT(functionCode() == QModbusPdu::WriteMultipleRegisters); } /// @@ -26,7 +37,7 @@ class WriteMultipleRegistersRequest : public ModbusMessage /// \return /// bool isValid() const override { - return ModbusMessage::isValid() && _data.size() > 5; + return ModbusMessage::isValid() && dataSize() > 5; } /// @@ -34,7 +45,7 @@ class WriteMultipleRegistersRequest : public ModbusMessage /// \return /// quint16 startAddress() const { - return makeWord(_data[1], _data[0], ByteOrder::LittleEndian); + return makeWord(data(1), data(0), ByteOrder::LittleEndian); } /// @@ -42,7 +53,7 @@ class WriteMultipleRegistersRequest : public ModbusMessage /// \return /// quint16 quantity() const { - return makeWord(_data[3], _data[2], ByteOrder::LittleEndian); + return makeWord(data(3), data(2), ByteOrder::LittleEndian); } /// @@ -50,7 +61,7 @@ class WriteMultipleRegistersRequest : public ModbusMessage /// \return /// quint8 byteCount() const { - return _data[4]; + return data(4); } /// @@ -58,7 +69,7 @@ class WriteMultipleRegistersRequest : public ModbusMessage /// \return /// QByteArray values() const { - return _data.right(_data.size() - 5); + return slice(5); } }; @@ -77,7 +88,18 @@ class WriteMultipleRegistersResponse : public ModbusMessage WriteMultipleRegistersResponse(const QModbusPdu& pdu, const QDateTime& timestamp, int deviceId) :ModbusMessage(pdu, timestamp, deviceId, false) { - Q_ASSERT((_funcCode & ~QModbusPdu::ExceptionByte) == QModbusPdu::WriteMultipleRegisters); + Q_ASSERT(functionCode() == QModbusPdu::WriteMultipleRegisters); + } + + /// + /// \brief WriteMultipleRegistersResponse + /// \param adu + /// \param timestamp + /// + WriteMultipleRegistersResponse(const QModbusAdu& adu, const QDateTime& timestamp) + : ModbusMessage(adu, timestamp, true) + { + Q_ASSERT(functionCode() == QModbusPdu::WriteMultipleRegisters); } /// @@ -85,7 +107,7 @@ class WriteMultipleRegistersResponse : public ModbusMessage /// \return /// bool isValid() const override { - return ModbusMessage::isValid() && _data.size() == 4; + return ModbusMessage::isValid() && dataSize() == 4; } /// @@ -93,7 +115,7 @@ class WriteMultipleRegistersResponse : public ModbusMessage /// \return /// quint16 startAddress() const { - return makeWord(_data[1], _data[0], ByteOrder::LittleEndian); + return makeWord(data(1), data(0), ByteOrder::LittleEndian); } /// @@ -101,7 +123,7 @@ class WriteMultipleRegistersResponse : public ModbusMessage /// \return /// quint16 quantity() const { - return makeWord(_data[3], _data[2], ByteOrder::LittleEndian); + return makeWord(data(3), data(2), ByteOrder::LittleEndian); } }; diff --git a/omodscan/modbusmessages/writesinglecoil.h b/omodscan/modbusmessages/writesinglecoil.h index c119fd5..0b4c401 100644 --- a/omodscan/modbusmessages/writesinglecoil.h +++ b/omodscan/modbusmessages/writesinglecoil.h @@ -18,7 +18,18 @@ class WriteSingleCoilRequest : public ModbusMessage WriteSingleCoilRequest(const QModbusPdu& pdu, const QDateTime& timestamp, int deviceId) : ModbusMessage(pdu, timestamp, deviceId, true) { - Q_ASSERT((_funcCode & ~QModbusPdu::ExceptionByte) == QModbusPdu::WriteSingleCoil); + Q_ASSERT(functionCode() == QModbusPdu::WriteSingleCoil); + } + + /// + /// \brief WriteSingleCoilRequest + /// \param adu + /// \param timestamp + /// + WriteSingleCoilRequest(const QModbusAdu& adu, const QDateTime& timestamp) + : ModbusMessage(adu, timestamp, true) + { + Q_ASSERT(functionCode() == QModbusPdu::WriteSingleCoil); } /// @@ -26,7 +37,7 @@ class WriteSingleCoilRequest : public ModbusMessage /// \return /// bool isValid() const override { - return ModbusMessage::isValid() && _data.size() == 4; + return ModbusMessage::isValid() && dataSize() == 4; } /// @@ -34,7 +45,7 @@ class WriteSingleCoilRequest : public ModbusMessage /// \return /// quint16 address() const { - return makeWord(_data[1], _data[0], ByteOrder::LittleEndian); + return makeWord(data(1), data(0), ByteOrder::LittleEndian); } /// @@ -42,7 +53,7 @@ class WriteSingleCoilRequest : public ModbusMessage /// \return /// quint16 value() const { - return makeWord(_data[3], _data[2], ByteOrder::LittleEndian); + return makeWord(data(3), data(2), ByteOrder::LittleEndian); } }; @@ -61,7 +72,18 @@ class WriteSingleCoilResponse : public ModbusMessage WriteSingleCoilResponse(const QModbusPdu& pdu, const QDateTime& timestamp, int deviceId) :ModbusMessage(pdu, timestamp, deviceId, false) { - Q_ASSERT((_funcCode & ~QModbusPdu::ExceptionByte) == QModbusPdu::WriteSingleCoil); + Q_ASSERT(functionCode() == QModbusPdu::WriteSingleCoil); + } + + /// + /// \brief WriteSingleCoilResponse + /// \param adu + /// \param timestamp + /// + WriteSingleCoilResponse(const QModbusAdu& adu, const QDateTime& timestamp) + : ModbusMessage(adu, timestamp, true) + { + Q_ASSERT(functionCode() == QModbusPdu::WriteSingleCoil); } /// @@ -69,7 +91,7 @@ class WriteSingleCoilResponse : public ModbusMessage /// \return /// bool isValid() const override { - return ModbusMessage::isValid() && _data.size() == 4; + return ModbusMessage::isValid() && dataSize() == 4; } /// @@ -77,7 +99,7 @@ class WriteSingleCoilResponse : public ModbusMessage /// \return /// quint16 address() const { - return makeWord(_data[1], _data[0], ByteOrder::LittleEndian); + return makeWord(data(1), data(0), ByteOrder::LittleEndian); } /// @@ -85,7 +107,7 @@ class WriteSingleCoilResponse : public ModbusMessage /// \return /// quint16 value() const { - return makeWord(_data[3], _data[2], ByteOrder::LittleEndian); + return makeWord(data(3), data(2), ByteOrder::LittleEndian); } }; diff --git a/omodscan/modbusmessages/writesingleregister.h b/omodscan/modbusmessages/writesingleregister.h index 00ece7e..b6ecb7c 100644 --- a/omodscan/modbusmessages/writesingleregister.h +++ b/omodscan/modbusmessages/writesingleregister.h @@ -18,7 +18,18 @@ class WriteSingleRegisterRequest : public ModbusMessage WriteSingleRegisterRequest(const QModbusPdu& pdu, const QDateTime& timestamp, int deviceId) : ModbusMessage(pdu, timestamp, deviceId, true) { - Q_ASSERT((_funcCode & ~QModbusPdu::ExceptionByte) == QModbusPdu::WriteSingleRegister); + Q_ASSERT(functionCode() == QModbusPdu::WriteSingleRegister); + } + + /// + /// \brief WriteSingleRegisterRequest + /// \param adu + /// \param timestamp + /// + WriteSingleRegisterRequest(const QModbusAdu& adu, const QDateTime& timestamp) + : ModbusMessage(adu, timestamp, true) + { + Q_ASSERT(functionCode() == QModbusPdu::WriteSingleRegister); } /// @@ -26,7 +37,7 @@ class WriteSingleRegisterRequest : public ModbusMessage /// \return /// bool isValid() const override { - return ModbusMessage::isValid() && _data.size() == 4; + return ModbusMessage::isValid() && dataSize() == 4; } /// @@ -34,7 +45,7 @@ class WriteSingleRegisterRequest : public ModbusMessage /// \return /// quint16 address() const { - return makeWord(_data[1], _data[0], ByteOrder::LittleEndian); + return makeWord(data(1), data(0), ByteOrder::LittleEndian); } /// @@ -42,7 +53,7 @@ class WriteSingleRegisterRequest : public ModbusMessage /// \return /// quint16 value() const { - return makeWord(_data[3], _data[2], ByteOrder::LittleEndian); + return makeWord(data(3), data(2), ByteOrder::LittleEndian); } }; @@ -61,7 +72,18 @@ class WriteSingleRegisterResponse : public ModbusMessage WriteSingleRegisterResponse(const QModbusPdu& pdu, const QDateTime& timestamp, int deviceId) :ModbusMessage(pdu, timestamp, deviceId, false) { - Q_ASSERT((_funcCode & ~QModbusPdu::ExceptionByte) == QModbusPdu::WriteSingleRegister); + Q_ASSERT(functionCode() == QModbusPdu::WriteSingleRegister); + } + + /// + /// \brief WriteSingleRegisterResponse + /// \param adu + /// \param timestamp + /// + WriteSingleRegisterResponse(const QModbusAdu& adu, const QDateTime& timestamp) + : ModbusMessage(adu, timestamp, true) + { + Q_ASSERT(functionCode() == QModbusPdu::WriteSingleRegister); } /// @@ -69,7 +91,7 @@ class WriteSingleRegisterResponse : public ModbusMessage /// \return /// bool isValid() const override { - return ModbusMessage::isValid() && _data.size() == 4; + return ModbusMessage::isValid() && dataSize() == 4; } /// @@ -77,7 +99,7 @@ class WriteSingleRegisterResponse : public ModbusMessage /// \return /// quint16 address() const { - return makeWord(_data[1], _data[0], ByteOrder::LittleEndian); + return makeWord(data(1), data(0), ByteOrder::LittleEndian); } /// @@ -85,7 +107,7 @@ class WriteSingleRegisterResponse : public ModbusMessage /// \return /// quint16 value() const { - return makeWord(_data[3], _data[2], ByteOrder::LittleEndian); + return makeWord(data(3), data(2), ByteOrder::LittleEndian); } }; diff --git a/omodscan/numericutils.h b/omodscan/numericutils.h index 7a7b767..5a3727e 100644 --- a/omodscan/numericutils.h +++ b/omodscan/numericutils.h @@ -24,6 +24,25 @@ inline quint16 makeWord(quint8 lo, quint8 hi, ByteOrder order) return v.asUint16; } +/// +/// \brief breakWord +/// \param value +/// \param lo +/// \param hi +/// \param order +/// +inline void breakWord(quint16 value, quint8& lo, quint8& hi, ByteOrder order) +{ + union { + quint8 asUint8[2]; + quint16 asUint16; + } v; + v.asUint16 = value; + + lo = (order == ByteOrder::LittleEndian) ? v.asUint8[0] : v.asUint8[1]; + hi = (order == ByteOrder::LittleEndian) ? v.asUint8[1] : v.asUint8[0]; +} + /// /// \brief breakFloat /// \param value diff --git a/omodscan/omodscan.pro b/omodscan/omodscan.pro index 547e461..d94fe6b 100644 --- a/omodscan/omodscan.pro +++ b/omodscan/omodscan.pro @@ -166,6 +166,7 @@ HEADERS += \ numericutils.h \ qfixedsizedialog.h \ qhexvalidator.h \ + qmodbusadu.h \ qrange.h \ quintvalidator.h \ recentfileactionlist.h \ diff --git a/omodscan/qmodbusadu.h b/omodscan/qmodbusadu.h new file mode 100644 index 0000000..72a4bf6 --- /dev/null +++ b/omodscan/qmodbusadu.h @@ -0,0 +1,163 @@ +#ifndef QMODBUSADU_H +#define QMODBUSADU_H + +#include +#include +#include "numericutils.h" + +class QModbusAdu +{ +public: + enum Type { + Rtu, + Tcp + }; + + /// + /// \brief QModbusAdu + /// \param type + /// \param data + /// + explicit QModbusAdu(Type type, const QByteArray &data) + : _type(type), _data(data) + { + _pdu.setFunctionCode(QModbusPdu::FunctionCode(_data[1])); + if(_type == Rtu) + _pdu.setData(_data.mid(7, _data.size() - 9)); + else + _pdu.setData(_data.mid(7, _data.size() - 7)); + } + + /// + /// \brief isValid + /// \return + /// + bool isValid() const { + return _data.size() > 6 && matchingChecksum() && _pdu.isValid(); + } + + /// + /// \brief data + /// \return + /// + QByteArray data() const { return _data; } + + /// + /// \brief setData + /// \param data + /// + void setData(const QByteArray& data) { _data = data; } + + /// + /// \brief transactionId + /// \return + /// + quint16 transactionId() const { + return makeWord(_data[0], _data[1], ByteOrder::LittleEndian); + } + + /// + /// \brief protocolId + /// \return + /// + quint16 protocolId() const { + return makeWord(_data[2], _data[3], ByteOrder::LittleEndian); + } + + /// + /// \brief length + /// \return + /// + quint16 length() const { + return makeWord(_data[4], _data[5], ByteOrder::LittleEndian); + } + + /// + /// \brief serverAddress + /// \return + /// + quint8 serverAddress() const { + return quint8(_data[6]); + } + + /// + /// \brief functionCode + /// \return + /// + QModbusPdu::FunctionCode functionCode() const { + return _pdu.functionCode(); + } + + /// + /// \brief exceptionCode + /// \return + /// + QModbusPdu::ExceptionCode exceptionCode() const { + return _pdu.exceptionCode(); + } + + /// + /// \brief isException + /// \return + /// + bool isException() const { + return _pdu.isException(); + } + + /// + /// \brief checksum + /// \return + /// + quint16 checksum() const { + return _type == Rtu ? quint16(quint8(_data[_data.size() - 2]) << 8 | quint8(_data[_data.size() - 1])) : quint16(0); + } + + /// + /// \brief matchingChecksum + /// \return + /// + bool matchingChecksum() const { + if(_type == Rtu) + { + const auto size = _data.size() - 2; // two bytes, CRC + const auto data = _data.left(size); + return QModbusAdu::calculateCRC(data, size) == checksum(); + } + return true; + } + +private: + inline static quint16 calculateCRC(const char *data, qint32 len){ + quint16 crc = 0xFFFF; + while (len--) { + const quint8 c = *data++; + for (qint32 i = 0x01; i & 0xFF; i <<= 1) { + bool bit = crc & 0x8000; + if (c & i) + bit = !bit; + crc <<= 1; + if (bit) + crc ^= 0x8005; + } + crc &= 0xFFFF; + } + crc = crc_reflect(crc & 0xFFFF, 16) ^ 0x0000; + return (crc >> 8) | (crc << 8); // swap bytes + } + + inline static quint16 crc_reflect(quint16 data, qint32 len){ + quint16 ret = data & 0x01; + for (qint32 i = 1; i < len; i++) { + data >>= 1; + ret = (ret << 1) | (data & 0x01); + } + return ret; + } + +private: + Type _type = Rtu; + QByteArray _data; + QModbusPdu _pdu; +}; + +#endif // QMODBUSADU_H From 26f0c93d845e15e08fe3f705e53c4b66f3ccb10a Mon Sep 17 00:00:00 2001 From: sanny32 Date: Mon, 9 Oct 2023 17:24:51 +0300 Subject: [PATCH 67/90] Developing modbus message parser --- omodscan/modbusmessages/diagnostics.h | 2 +- omodscan/modbusmessages/getcommeventcounter.h | 2 +- omodscan/modbusmessages/getcommeventlog.h | 2 +- omodscan/modbusmessages/maskwriteregister.h | 2 +- omodscan/modbusmessages/modbusmessage.cpp | 1 - omodscan/modbusmessages/modbusmessage.h | 6 ++-- omodscan/modbusmessages/readcoils.h | 2 +- omodscan/modbusmessages/readdiscreteinputs.h | 2 +- omodscan/modbusmessages/readexceptionstatus.h | 2 +- omodscan/modbusmessages/readfifoqueue.h | 2 +- omodscan/modbusmessages/readfilerecord.h | 2 +- .../modbusmessages/readholdingregisters.h | 2 +- omodscan/modbusmessages/readinputregisters.h | 2 +- .../readwritemultipleregisters.h | 2 +- omodscan/modbusmessages/reportserverid.h | 2 +- omodscan/modbusmessages/writefilerecord.h | 2 +- omodscan/modbusmessages/writemultiplecoils.h | 2 +- .../modbusmessages/writemultipleregisters.h | 2 +- omodscan/modbusmessages/writesinglecoil.h | 2 +- omodscan/modbusmessages/writesingleregister.h | 2 +- omodscan/qmodbusadu.h | 29 +++++++++++-------- 21 files changed, 38 insertions(+), 34 deletions(-) diff --git a/omodscan/modbusmessages/diagnostics.h b/omodscan/modbusmessages/diagnostics.h index 481c862..abecb31 100644 --- a/omodscan/modbusmessages/diagnostics.h +++ b/omodscan/modbusmessages/diagnostics.h @@ -82,7 +82,7 @@ class DiagnosticsResponse : public ModbusMessage /// \param timestamp /// DiagnosticsResponse(const QModbusAdu& adu, const QDateTime& timestamp) - : ModbusMessage(adu, timestamp, true) + : ModbusMessage(adu, timestamp, false) { Q_ASSERT(functionCode() == QModbusPdu::Diagnostics); } diff --git a/omodscan/modbusmessages/getcommeventcounter.h b/omodscan/modbusmessages/getcommeventcounter.h index b820f3c..5db1f62 100644 --- a/omodscan/modbusmessages/getcommeventcounter.h +++ b/omodscan/modbusmessages/getcommeventcounter.h @@ -57,7 +57,7 @@ class GetCommEventCounterResponse : public ModbusMessage /// \param timestamp /// GetCommEventCounterResponse(const QModbusAdu& adu, const QDateTime& timestamp) - : ModbusMessage(adu, timestamp, true) + : ModbusMessage(adu, timestamp, false) { Q_ASSERT(functionCode() == QModbusPdu::GetCommEventCounter); } diff --git a/omodscan/modbusmessages/getcommeventlog.h b/omodscan/modbusmessages/getcommeventlog.h index 6d3586f..ce391f7 100644 --- a/omodscan/modbusmessages/getcommeventlog.h +++ b/omodscan/modbusmessages/getcommeventlog.h @@ -57,7 +57,7 @@ class GetCommEventLogResponse : public ModbusMessage /// \param timestamp /// GetCommEventLogResponse(const QModbusAdu& adu, const QDateTime& timestamp) - : ModbusMessage(adu, timestamp, true) + : ModbusMessage(adu, timestamp, false) { Q_ASSERT(functionCode() == QModbusPdu::GetCommEventLog); } diff --git a/omodscan/modbusmessages/maskwriteregister.h b/omodscan/modbusmessages/maskwriteregister.h index 412b865..f388b1a 100644 --- a/omodscan/modbusmessages/maskwriteregister.h +++ b/omodscan/modbusmessages/maskwriteregister.h @@ -89,7 +89,7 @@ class MaskWriteRegisterResponse : public ModbusMessage /// \param timestamp /// MaskWriteRegisterResponse(const QModbusAdu& adu, const QDateTime& timestamp) - : ModbusMessage(adu, timestamp, true) + : ModbusMessage(adu, timestamp, false) { Q_ASSERT(functionCode() == QModbusPdu::MaskWriteRegister); } diff --git a/omodscan/modbusmessages/modbusmessage.cpp b/omodscan/modbusmessages/modbusmessage.cpp index a1df3ec..983982d 100644 --- a/omodscan/modbusmessages/modbusmessage.cpp +++ b/omodscan/modbusmessages/modbusmessage.cpp @@ -188,7 +188,6 @@ const ModbusMessage* ModbusMessage::create(const QModbusAdu& adu, const QDateTim /// const ModbusMessage* ModbusMessage::parse(const QByteArray& data, Type type, QModbusAdu::Type protocol, bool request) { - switch(type) { case Adu: diff --git a/omodscan/modbusmessages/modbusmessage.h b/omodscan/modbusmessages/modbusmessage.h index d3d3f9a..165ba9a 100644 --- a/omodscan/modbusmessages/modbusmessage.h +++ b/omodscan/modbusmessages/modbusmessage.h @@ -236,7 +236,7 @@ class ModbusMessage switch(_type) { case Adu: - return _data.size() - 7; + return _data.size() - 8; case Pdu: return _data.size(); @@ -248,7 +248,7 @@ class ModbusMessage switch(_type) { case Adu: - return _data[7 + idx]; + return _data[8 + idx]; case Pdu: return _data[idx]; @@ -260,7 +260,7 @@ class ModbusMessage switch(_type) { case Adu: - return _data.mid(idx + 7, len); + return _data.mid(idx + 8, len); case Pdu: return _data.mid(idx, len); diff --git a/omodscan/modbusmessages/readcoils.h b/omodscan/modbusmessages/readcoils.h index a06353a..3e2bcf0 100644 --- a/omodscan/modbusmessages/readcoils.h +++ b/omodscan/modbusmessages/readcoils.h @@ -82,7 +82,7 @@ class ReadCoilsResponse : public ModbusMessage /// \param timestamp /// ReadCoilsResponse(const QModbusAdu& adu, const QDateTime& timestamp) - : ModbusMessage(adu, timestamp, true) + : ModbusMessage(adu, timestamp, false) { Q_ASSERT(functionCode() == QModbusPdu::ReadCoils); } diff --git a/omodscan/modbusmessages/readdiscreteinputs.h b/omodscan/modbusmessages/readdiscreteinputs.h index 87f426f..1ae993f 100644 --- a/omodscan/modbusmessages/readdiscreteinputs.h +++ b/omodscan/modbusmessages/readdiscreteinputs.h @@ -81,7 +81,7 @@ class ReadDiscreteInputsResponse : public ModbusMessage /// \param timestamp /// ReadDiscreteInputsResponse(const QModbusAdu& adu, const QDateTime& timestamp) - : ModbusMessage(adu, timestamp, true) + : ModbusMessage(adu, timestamp, false) { Q_ASSERT(functionCode() == QModbusPdu::ReadDiscreteInputs); } diff --git a/omodscan/modbusmessages/readexceptionstatus.h b/omodscan/modbusmessages/readexceptionstatus.h index 210f98a..4a760da 100644 --- a/omodscan/modbusmessages/readexceptionstatus.h +++ b/omodscan/modbusmessages/readexceptionstatus.h @@ -57,7 +57,7 @@ class ReadExceptionStatusResponse : public ModbusMessage /// \param timestamp /// ReadExceptionStatusResponse(const QModbusAdu& adu, const QDateTime& timestamp) - : ModbusMessage(adu, timestamp, true) + : ModbusMessage(adu, timestamp, false) { Q_ASSERT(functionCode() == QModbusPdu::ReadExceptionStatus); } diff --git a/omodscan/modbusmessages/readfifoqueue.h b/omodscan/modbusmessages/readfifoqueue.h index 001431b..1fbdb2d 100644 --- a/omodscan/modbusmessages/readfifoqueue.h +++ b/omodscan/modbusmessages/readfifoqueue.h @@ -73,7 +73,7 @@ class ReadFifoQueueResponse : public ModbusMessage /// \param timestamp /// ReadFifoQueueResponse(const QModbusAdu& adu, const QDateTime& timestamp) - : ModbusMessage(adu, timestamp, true) + : ModbusMessage(adu, timestamp, false) { Q_ASSERT(functionCode() == QModbusPdu::ReadFifoQueue); } diff --git a/omodscan/modbusmessages/readfilerecord.h b/omodscan/modbusmessages/readfilerecord.h index cc510e7..e5c3d89 100644 --- a/omodscan/modbusmessages/readfilerecord.h +++ b/omodscan/modbusmessages/readfilerecord.h @@ -81,7 +81,7 @@ class ReadFileRecordResponse : public ModbusMessage /// \param timestamp /// ReadFileRecordResponse(const QModbusAdu& adu, const QDateTime& timestamp) - : ModbusMessage(adu, timestamp, true) + : ModbusMessage(adu, timestamp, false) { Q_ASSERT(functionCode() == QModbusPdu::ReadFileRecord); } diff --git a/omodscan/modbusmessages/readholdingregisters.h b/omodscan/modbusmessages/readholdingregisters.h index 4478f0b..9dba4ff 100644 --- a/omodscan/modbusmessages/readholdingregisters.h +++ b/omodscan/modbusmessages/readholdingregisters.h @@ -81,7 +81,7 @@ class ReadHoldingRegistersResponse : public ModbusMessage /// \param timestamp /// ReadHoldingRegistersResponse(const QModbusAdu& adu, const QDateTime& timestamp) - : ModbusMessage(adu, timestamp, true) + : ModbusMessage(adu, timestamp, false) { Q_ASSERT(functionCode() == QModbusPdu::ReadHoldingRegisters); } diff --git a/omodscan/modbusmessages/readinputregisters.h b/omodscan/modbusmessages/readinputregisters.h index a637303..c444cf5 100644 --- a/omodscan/modbusmessages/readinputregisters.h +++ b/omodscan/modbusmessages/readinputregisters.h @@ -81,7 +81,7 @@ class ReadInputRegistersResponse : public ModbusMessage /// \param timestamp /// ReadInputRegistersResponse(const QModbusAdu& adu, const QDateTime& timestamp) - : ModbusMessage(adu, timestamp, true) + : ModbusMessage(adu, timestamp, false) { Q_ASSERT(functionCode() == QModbusPdu::ReadInputRegisters); } diff --git a/omodscan/modbusmessages/readwritemultipleregisters.h b/omodscan/modbusmessages/readwritemultipleregisters.h index 7df148f..3b50f4c 100644 --- a/omodscan/modbusmessages/readwritemultipleregisters.h +++ b/omodscan/modbusmessages/readwritemultipleregisters.h @@ -113,7 +113,7 @@ class ReadWriteMultipleRegistersResponse : public ModbusMessage /// \param timestamp /// ReadWriteMultipleRegistersResponse(const QModbusAdu& adu, const QDateTime& timestamp) - : ModbusMessage(adu, timestamp, true) + : ModbusMessage(adu, timestamp, false) { Q_ASSERT(functionCode() == QModbusPdu::ReadWriteMultipleRegisters); } diff --git a/omodscan/modbusmessages/reportserverid.h b/omodscan/modbusmessages/reportserverid.h index 9b23b47..a358647 100644 --- a/omodscan/modbusmessages/reportserverid.h +++ b/omodscan/modbusmessages/reportserverid.h @@ -57,7 +57,7 @@ class ReportServerIdResponse : public ModbusMessage /// \param timestamp /// ReportServerIdResponse(const QModbusAdu& adu, const QDateTime& timestamp) - : ModbusMessage(adu, timestamp, true) + : ModbusMessage(adu, timestamp, false) { Q_ASSERT(functionCode() == QModbusPdu::ReportServerId); } diff --git a/omodscan/modbusmessages/writefilerecord.h b/omodscan/modbusmessages/writefilerecord.h index d0661c4..beb3c44 100644 --- a/omodscan/modbusmessages/writefilerecord.h +++ b/omodscan/modbusmessages/writefilerecord.h @@ -81,7 +81,7 @@ class WriteFileRecordResponse : public ModbusMessage /// \param timestamp /// WriteFileRecordResponse(const QModbusAdu& adu, const QDateTime& timestamp) - : ModbusMessage(adu, timestamp, true) + : ModbusMessage(adu, timestamp, false) { Q_ASSERT(functionCode() == QModbusPdu::WriteFileRecord); } diff --git a/omodscan/modbusmessages/writemultiplecoils.h b/omodscan/modbusmessages/writemultiplecoils.h index 5e64d5f..62ce370 100644 --- a/omodscan/modbusmessages/writemultiplecoils.h +++ b/omodscan/modbusmessages/writemultiplecoils.h @@ -97,7 +97,7 @@ class WriteMultipleCoilsResponse : public ModbusMessage /// \param timestamp /// WriteMultipleCoilsResponse(const QModbusAdu& adu, const QDateTime& timestamp) - : ModbusMessage(adu, timestamp, true) + : ModbusMessage(adu, timestamp, false) { Q_ASSERT(functionCode() == QModbusPdu::WriteMultipleCoils); } diff --git a/omodscan/modbusmessages/writemultipleregisters.h b/omodscan/modbusmessages/writemultipleregisters.h index f4e5ba4..99cb478 100644 --- a/omodscan/modbusmessages/writemultipleregisters.h +++ b/omodscan/modbusmessages/writemultipleregisters.h @@ -97,7 +97,7 @@ class WriteMultipleRegistersResponse : public ModbusMessage /// \param timestamp /// WriteMultipleRegistersResponse(const QModbusAdu& adu, const QDateTime& timestamp) - : ModbusMessage(adu, timestamp, true) + : ModbusMessage(adu, timestamp, false) { Q_ASSERT(functionCode() == QModbusPdu::WriteMultipleRegisters); } diff --git a/omodscan/modbusmessages/writesinglecoil.h b/omodscan/modbusmessages/writesinglecoil.h index 0b4c401..cfa90c8 100644 --- a/omodscan/modbusmessages/writesinglecoil.h +++ b/omodscan/modbusmessages/writesinglecoil.h @@ -81,7 +81,7 @@ class WriteSingleCoilResponse : public ModbusMessage /// \param timestamp /// WriteSingleCoilResponse(const QModbusAdu& adu, const QDateTime& timestamp) - : ModbusMessage(adu, timestamp, true) + : ModbusMessage(adu, timestamp, false) { Q_ASSERT(functionCode() == QModbusPdu::WriteSingleCoil); } diff --git a/omodscan/modbusmessages/writesingleregister.h b/omodscan/modbusmessages/writesingleregister.h index b6ecb7c..048ce36 100644 --- a/omodscan/modbusmessages/writesingleregister.h +++ b/omodscan/modbusmessages/writesingleregister.h @@ -81,7 +81,7 @@ class WriteSingleRegisterResponse : public ModbusMessage /// \param timestamp /// WriteSingleRegisterResponse(const QModbusAdu& adu, const QDateTime& timestamp) - : ModbusMessage(adu, timestamp, true) + : ModbusMessage(adu, timestamp, false) { Q_ASSERT(functionCode() == QModbusPdu::WriteSingleRegister); } diff --git a/omodscan/qmodbusadu.h b/omodscan/qmodbusadu.h index 72a4bf6..65db306 100644 --- a/omodscan/qmodbusadu.h +++ b/omodscan/qmodbusadu.h @@ -18,14 +18,10 @@ class QModbusAdu /// \param type /// \param data /// - explicit QModbusAdu(Type type, const QByteArray &data) - : _type(type), _data(data) + explicit QModbusAdu(Type type, const QByteArray& data) + : _type(type) { - _pdu.setFunctionCode(QModbusPdu::FunctionCode(_data[1])); - if(_type == Rtu) - _pdu.setData(_data.mid(7, _data.size() - 9)); - else - _pdu.setData(_data.mid(7, _data.size() - 7)); + setData(data); } /// @@ -46,14 +42,14 @@ class QModbusAdu /// \brief setData /// \param data /// - void setData(const QByteArray& data) { _data = data; } + void setData(const QByteArray& data) { _data = data; update(); } /// /// \brief transactionId /// \return /// quint16 transactionId() const { - return makeWord(_data[0], _data[1], ByteOrder::LittleEndian); + return makeWord(_data[1], _data[0], ByteOrder::LittleEndian); } /// @@ -61,7 +57,7 @@ class QModbusAdu /// \return /// quint16 protocolId() const { - return makeWord(_data[2], _data[3], ByteOrder::LittleEndian); + return makeWord(_data[3], _data[2], ByteOrder::LittleEndian); } /// @@ -69,7 +65,7 @@ class QModbusAdu /// \return /// quint16 length() const { - return makeWord(_data[4], _data[5], ByteOrder::LittleEndian); + return makeWord(_data[5], _data[4], ByteOrder::LittleEndian); } /// @@ -127,6 +123,15 @@ class QModbusAdu } private: + void update() + { + _pdu.setFunctionCode(QModbusPdu::FunctionCode(_data[7])); + if(_type == Rtu) + _pdu.setData(_data.mid(8, _data.size() - 10)); + else + _pdu.setData(_data.mid(8)); + } + inline static quint16 calculateCRC(const char *data, qint32 len){ quint16 crc = 0xFFFF; while (len--) { @@ -155,7 +160,7 @@ class QModbusAdu } private: - Type _type = Rtu; + Type _type; QByteArray _data; QModbusPdu _pdu; }; From 878d866f4bf796365140cef84c80b4e5e710d739 Mon Sep 17 00:00:00 2001 From: sanny32 Date: Tue, 10 Oct 2023 12:01:03 +0300 Subject: [PATCH 68/90] Developing modbus message parser --- omodscan/controls/modbuslogwidget.cpp | 22 +++-- omodscan/controls/modbuslogwidget.h | 2 +- omodscan/controls/modbusmessagewidget.cpp | 10 ++ omodscan/controls/outputwidget.cpp | 21 ++--- omodscan/dialogs/dialogaddressscan.cpp | 4 +- omodscan/dialogs/dialogmsgparser.cpp | 25 +++-- omodscan/dialogs/dialogmsgparser.h | 2 + omodscan/dialogs/dialogmsgparser.ui | 16 ++-- omodscan/dialogs/dialogusermsg.cpp | 15 +-- omodscan/dialogs/dialogusermsg.h | 2 + omodscan/modbusmessages/diagnostics.h | 14 +-- omodscan/modbusmessages/getcommeventcounter.h | 14 +-- omodscan/modbusmessages/getcommeventlog.h | 18 ++-- omodscan/modbusmessages/maskwriteregister.h | 14 +-- omodscan/modbusmessages/modbusmessage.cpp | 93 +++++++++++-------- omodscan/modbusmessages/modbusmessage.h | 45 ++++++++- omodscan/modbusmessages/readcoils.h | 21 +++-- omodscan/modbusmessages/readdiscreteinputs.h | 21 +++-- omodscan/modbusmessages/readexceptionstatus.h | 14 +-- omodscan/modbusmessages/readfifoqueue.h | 18 ++-- omodscan/modbusmessages/readfilerecord.h | 20 ++-- .../modbusmessages/readholdingregisters.h | 21 +++-- omodscan/modbusmessages/readinputregisters.h | 21 +++-- .../readwritemultipleregisters.h | 24 +++-- omodscan/modbusmessages/reportserverid.h | 14 +-- omodscan/modbusmessages/writefilerecord.h | 22 +++-- omodscan/modbusmessages/writemultiplecoils.h | 18 ++-- .../modbusmessages/writemultipleregisters.h | 18 ++-- omodscan/modbusmessages/writesinglecoil.h | 20 ++-- omodscan/modbusmessages/writesingleregister.h | 14 +-- omodscan/qmodbusadu.h | 35 ++++--- 31 files changed, 379 insertions(+), 239 deletions(-) diff --git a/omodscan/controls/modbuslogwidget.cpp b/omodscan/controls/modbuslogwidget.cpp index f1c771c..514a7d7 100644 --- a/omodscan/controls/modbuslogwidget.cpp +++ b/omodscan/controls/modbuslogwidget.cpp @@ -162,14 +162,20 @@ QModelIndex ModbusLogWidget::index(int row) /// /// \brief ModbusLogWidget::addItem /// \param pdu -/// \param timestamp /// \param deviceId +/// \param timestamp /// \param request +/// \return /// -void ModbusLogWidget::addItem(const QModbusPdu& pdu, const QDateTime& timestamp, int deviceId, bool request) +const ModbusMessage* ModbusLogWidget::addItem(const QModbusPdu& pdu, int deviceId, const QDateTime& timestamp, bool request) { + const ModbusMessage* msg = nullptr; if(model()) - ((ModbusLogModel*)model())->append(ModbusMessage::create(pdu, timestamp, deviceId, request)); + { + msg = ModbusMessage::create(pdu, (QModbusAdu::Type)-1, deviceId, timestamp, request); + ((ModbusLogModel*)model())->append(msg); + } + return msg; } /// @@ -183,8 +189,8 @@ const ModbusMessage* ModbusLogWidget::itemAt(const QModelIndex& index) return nullptr; return model() ? - model()->data(index, Qt::UserRole).value() : - nullptr; + model()->data(index, Qt::UserRole).value() : + nullptr; } /// @@ -204,8 +210,9 @@ void ModbusLogWidget::setDataDisplayMode(DataDisplayMode mode) { _dataDisplayMode = mode; - if(model()) + if(model()) { ((ModbusLogModel*)model())->update(); + } } /// @@ -223,8 +230,9 @@ int ModbusLogWidget::rowLimit() const /// void ModbusLogWidget::setRowLimit(int val) { - if(model()) + if(model()) { ((ModbusLogModel*)model())->setRowLimit(val); + } } /// diff --git a/omodscan/controls/modbuslogwidget.h b/omodscan/controls/modbuslogwidget.h index 2b8f9e9..bf541d7 100644 --- a/omodscan/controls/modbuslogwidget.h +++ b/omodscan/controls/modbuslogwidget.h @@ -53,7 +53,7 @@ class ModbusLogWidget : public QListView int rowCount() const; QModelIndex index(int row); - void addItem(const QModbusPdu& pdu, const QDateTime& timestamp, int deviceId, bool request); + const ModbusMessage* addItem(const QModbusPdu& pdu, int deviceId, const QDateTime& timestamp, bool request); const ModbusMessage* itemAt(const QModelIndex& index); DataDisplayMode dataDisplayMode() const; diff --git a/omodscan/controls/modbusmessagewidget.cpp b/omodscan/controls/modbusmessagewidget.cpp index fa6eabc..90c665a 100644 --- a/omodscan/controls/modbusmessagewidget.cpp +++ b/omodscan/controls/modbusmessagewidget.cpp @@ -122,6 +122,13 @@ void ModbusMessageWidget::update() addItem(tr("*** INVALID MODBUS RESPONSE ***")); } + auto addChecksum = [&]{ + if(_msg->protocolType() == QModbusAdu::Rtu) + { + addItem(tr("Checksum: %1").arg(formatWordValue(_dataDisplayMode, _msg->checksum()))); + } + }; + addItem(tr("Type: %1").arg(_msg->isRequest() ? tr("Tx Message") : tr("Rx Message"))); if(_showTimestamp) addItem(tr("Timestamp: %1").arg(_msg->timestamp().toString(Qt::ISODateWithMs))); @@ -139,6 +146,7 @@ void ModbusMessageWidget::update() const auto exception = QString("%1 (%2)").arg(formatByteValue(_dataDisplayMode, _msg->exception()), _msg->exception()); addItem(tr("Error Code: %1").arg(formatByteValue(_dataDisplayMode, _msg->function()))); addItem(tr("Exception Code: %1").arg(exception)); + addChecksum(); return; } @@ -491,4 +499,6 @@ void ModbusMessageWidget::update() } break; } + + addChecksum(); } diff --git a/omodscan/controls/outputwidget.cpp b/omodscan/controls/outputwidget.cpp index 03547c7..3a6a2ad 100644 --- a/omodscan/controls/outputwidget.cpp +++ b/omodscan/controls/outputwidget.cpp @@ -821,20 +821,13 @@ void OutputWidget::showModbusMessage(const QModelIndex& index) /// void OutputWidget::updateLogView(bool request, int server, const QModbusPdu& pdu) { - ui->logView->addItem(pdu, QDateTime::currentDateTime(), server, request); - - if(captureMode() == CaptureMode::TextCapture) + auto msg = ui->logView->addItem(pdu, server, QDateTime::currentDateTime(), request); + if(captureMode() == CaptureMode::TextCapture && msg != nullptr) { - const auto idx = ui->logView->index(ui->logView->rowCount() - 1); - const auto msg = ui->logView->itemAt(idx); - - if(msg != nullptr) - { - const auto str = QString("%1 %2 %3").arg( - msg->timestamp().toString(Qt::ISODateWithMs), - (msg->isRequest()? "<<" : ">>"), - msg->toString(DataDisplayMode::Hex)); - captureString(str); - } + const auto str = QString("%1 %2 %3").arg( + msg->timestamp().toString(Qt::ISODateWithMs), + (msg->isRequest()? "<<" : ">>"), + msg->toString(DataDisplayMode::Hex)); + captureString(str); } } diff --git a/omodscan/dialogs/dialogaddressscan.cpp b/omodscan/dialogs/dialogaddressscan.cpp index 751d638..b57d8a6 100644 --- a/omodscan/dialogs/dialogaddressscan.cpp +++ b/omodscan/dialogs/dialogaddressscan.cpp @@ -594,7 +594,7 @@ void DialogAddressScan::updateLogView(int deviceId, const QModbusRequest& reques auto proxyLogModel = ((LogViewProxyModel*)ui->logView->model()); proxyLogModel->append(pointAddress + 1, ui->comboBoxPointType->currentPointType(), - ModbusMessage::create(request, QDateTime::currentDateTime(), deviceId, true)); + ModbusMessage::create(request, (QModbusAdu::Type)-1, deviceId, QDateTime::currentDateTime(), true)); } /// @@ -612,7 +612,7 @@ void DialogAddressScan::updateLogView(const QModbusReply* reply) auto proxyLogModel = ((LogViewProxyModel*)ui->logView->model()); proxyLogModel->append(pointAddress, ui->comboBoxPointType->currentPointType(), - ModbusMessage::create(pdu, QDateTime::currentDateTime(), deviceId, false)); + ModbusMessage::create(pdu, (QModbusAdu::Type)-1, deviceId, QDateTime::currentDateTime(), false)); } /// diff --git a/omodscan/dialogs/dialogmsgparser.cpp b/omodscan/dialogs/dialogmsgparser.cpp index 8f18649..90f7b04 100644 --- a/omodscan/dialogs/dialogmsgparser.cpp +++ b/omodscan/dialogs/dialogmsgparser.cpp @@ -1,6 +1,5 @@ #include #include -#include "modbusmessage.h" #include "dialogmsgparser.h" #include "ui_dialogmsgparser.h" @@ -12,6 +11,7 @@ DialogMsgParser::DialogMsgParser(DataDisplayMode mode, QWidget *parent) : QDialog(parent) , ui(new Ui::DialogMsgParser) + ,_mm(nullptr) { ui->setupUi(this); @@ -33,6 +33,7 @@ DialogMsgParser::DialogMsgParser(DataDisplayMode mode, QWidget *parent) DialogMsgParser::~DialogMsgParser() { delete ui; + if(_mm) delete _mm; } /// @@ -40,7 +41,7 @@ DialogMsgParser::~DialogMsgParser() /// void DialogMsgParser::on_awake() { - ui->rtu->setVisible(ui->buttonAdu->isChecked()); + //ui->rtu->setVisible(ui->buttonAdu->isChecked()); ui->deviceIdIncluded->setVisible(ui->buttonPdu->isChecked()); ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(!ui->bytesData->isEmpty()); } @@ -60,22 +61,18 @@ void DialogMsgParser::on_hexView_toggled(bool checked) /// void DialogMsgParser::accept() { - if(ui->info->modbusMessage()) - delete ui->info->modbusMessage(); + if(_mm) delete _mm; + + auto data = ui->bytesData->value(); + ModbusMessage::Type type = ModbusMessage::Adu; + const auto protocol = ui->checksum->isChecked() ? QModbusAdu::Rtu : QModbusAdu::Tcp; - const ModbusMessage* msg = nullptr; if(ui->buttonPdu->isChecked()) { - auto data = ui->bytesData->value(); + type = ModbusMessage::Pdu; if(!ui->deviceIdIncluded->isChecked()) data.push_front('\0'); - msg = ModbusMessage::parse(data, ModbusMessage::Pdu, QModbusAdu::Tcp, ui->request->isChecked()); - } - else if(ui->buttonAdu->isChecked()) - { - auto data = ui->bytesData->value(); - const auto protocol = ui->rtu->isChecked() ? QModbusAdu::Rtu : QModbusAdu::Tcp; - msg = ModbusMessage::parse(data, ModbusMessage::Adu, protocol, ui->request->isChecked()); } - ui->info->setModbusMessage(msg); + _mm = ModbusMessage::parse(data, type, protocol, ui->request->isChecked()); + ui->info->setModbusMessage(_mm); } diff --git a/omodscan/dialogs/dialogmsgparser.h b/omodscan/dialogs/dialogmsgparser.h index c1eede6..21fb970 100644 --- a/omodscan/dialogs/dialogmsgparser.h +++ b/omodscan/dialogs/dialogmsgparser.h @@ -3,6 +3,7 @@ #include #include "enums.h" +#include "modbusmessage.h" namespace Ui { class DialogMsgParser; @@ -27,6 +28,7 @@ private slots: private: Ui::DialogMsgParser *ui; + const ModbusMessage* _mm; }; #endif // DIALOGMSGPARSER_H diff --git a/omodscan/dialogs/dialogmsgparser.ui b/omodscan/dialogs/dialogmsgparser.ui index fcfab9b..5ed666f 100644 --- a/omodscan/dialogs/dialogmsgparser.ui +++ b/omodscan/dialogs/dialogmsgparser.ui @@ -97,13 +97,6 @@ - - - - Modbus RTU - - - @@ -114,13 +107,20 @@ - Device Id Included + Device Id included true + + + + Checksum included + + +
diff --git a/omodscan/dialogs/dialogusermsg.cpp b/omodscan/dialogs/dialogusermsg.cpp index fa48d38..c43c77f 100644 --- a/omodscan/dialogs/dialogusermsg.cpp +++ b/omodscan/dialogs/dialogusermsg.cpp @@ -2,7 +2,6 @@ #include #include #include -#include "modbusmessage.h" #include "modbuslimits.h" #include "dialogusermsg.h" #include "ui_dialogusermsg.h" @@ -15,9 +14,10 @@ /// \param client /// \param parent /// -DialogUserMsg::DialogUserMsg(quint8 slaveAddress, QModbusPdu::FunctionCode func, DataDisplayMode mode, ModbusClient& client, QWidget *parent) : - QDialog(parent) +DialogUserMsg::DialogUserMsg(quint8 slaveAddress, QModbusPdu::FunctionCode func, DataDisplayMode mode, ModbusClient& client, QWidget *parent) + : QDialog(parent) , ui(new Ui::DialogUserMsg) + ,_mm(nullptr) ,_modbusClient(client) { ui->setupUi(this); @@ -55,6 +55,7 @@ DialogUserMsg::DialogUserMsg(quint8 slaveAddress, QModbusPdu::FunctionCode func, DialogUserMsg::~DialogUserMsg() { delete ui; + if(_mm) delete _mm; } /// @@ -102,11 +103,11 @@ void DialogUserMsg::on_modbusReply(QModbusReply* reply) return; } - const auto response = reply->rawResult(); - const auto msg = ModbusMessage::create(response, QDateTime::currentDateTime(), reply->serverAddress(), false); + if(_mm) delete _mm; + _mm = ModbusMessage::create(reply->rawResult(), QModbusAdu::Tcp, reply->serverAddress(), QDateTime::currentDateTime(), false); - ui->responseBuffer->setValue(*msg); - ui->responseInfo->setModbusMessage(msg); + ui->responseBuffer->setValue(*_mm); + ui->responseInfo->setModbusMessage(_mm); ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(true); } diff --git a/omodscan/dialogs/dialogusermsg.h b/omodscan/dialogs/dialogusermsg.h index 3d60a56..30e2e3c 100644 --- a/omodscan/dialogs/dialogusermsg.h +++ b/omodscan/dialogs/dialogusermsg.h @@ -4,6 +4,7 @@ #include #include #include "modbusclient.h" +#include "modbusmessage.h" #include "enums.h" namespace Ui { @@ -27,6 +28,7 @@ private slots: private: Ui::DialogUserMsg *ui; + const ModbusMessage* _mm; ModbusClient& _modbusClient; }; diff --git a/omodscan/modbusmessages/diagnostics.h b/omodscan/modbusmessages/diagnostics.h index abecb31..d993f81 100644 --- a/omodscan/modbusmessages/diagnostics.h +++ b/omodscan/modbusmessages/diagnostics.h @@ -12,11 +12,12 @@ class DiagnosticsRequest : public ModbusMessage /// /// \brief DiagnosticsRequest /// \param pdu - /// \param timestamp + /// \param protocol /// \param deviceId + /// \param timestamp /// - DiagnosticsRequest(const QModbusPdu& pdu, const QDateTime& timestamp, int deviceId) - : ModbusMessage(pdu, timestamp, deviceId, true) + DiagnosticsRequest(const QModbusPdu& pdu, QModbusAdu::Type protocol, int deviceId, const QDateTime& timestamp) + : ModbusMessage(pdu, protocol, deviceId, timestamp, true) { Q_ASSERT(functionCode() == QModbusPdu::Diagnostics); } @@ -67,11 +68,12 @@ class DiagnosticsResponse : public ModbusMessage /// /// \brief DiagnosticsResponse /// \param pdu - /// \param timestamp + /// \param protocol /// \param deviceId + /// \param timestamp /// - DiagnosticsResponse(const QModbusPdu& pdu, const QDateTime& timestamp, int deviceId) - :ModbusMessage(pdu, timestamp, deviceId, false) + DiagnosticsResponse(const QModbusPdu& pdu, QModbusAdu::Type protocol, int deviceId, const QDateTime& timestamp) + :ModbusMessage(pdu, protocol, deviceId, timestamp, false) { Q_ASSERT(functionCode() == QModbusPdu::Diagnostics); } diff --git a/omodscan/modbusmessages/getcommeventcounter.h b/omodscan/modbusmessages/getcommeventcounter.h index 5db1f62..8aa7273 100644 --- a/omodscan/modbusmessages/getcommeventcounter.h +++ b/omodscan/modbusmessages/getcommeventcounter.h @@ -12,11 +12,12 @@ class GetCommEventCounterRequest : public ModbusMessage /// /// \brief GetCommEventCounterRequest /// \param pdu - /// \param timestamp + /// \param protocol /// \param deviceId + /// \param timestamp /// - GetCommEventCounterRequest(const QModbusPdu& pdu, const QDateTime& timestamp, int deviceId) - : ModbusMessage(pdu, timestamp, deviceId, true) + GetCommEventCounterRequest(const QModbusPdu& pdu, QModbusAdu::Type protocol, int deviceId, const QDateTime& timestamp) + : ModbusMessage(pdu, protocol, deviceId, timestamp, true) { Q_ASSERT(functionCode() == QModbusPdu::GetCommEventCounter); } @@ -42,11 +43,12 @@ class GetCommEventCounterResponse : public ModbusMessage /// /// \brief GetCommEventCounterResponse /// \param pdu - /// \param timestamp + /// \param protocol /// \param deviceId + /// \param timestamp /// - GetCommEventCounterResponse(const QModbusPdu& pdu, const QDateTime& timestamp, int deviceId) - :ModbusMessage(pdu, timestamp, deviceId, false) + GetCommEventCounterResponse(const QModbusPdu& pdu, QModbusAdu::Type protocol, int deviceId, const QDateTime& timestamp) + :ModbusMessage(pdu, protocol, deviceId, timestamp, false) { Q_ASSERT(functionCode() == QModbusPdu::GetCommEventCounter); } diff --git a/omodscan/modbusmessages/getcommeventlog.h b/omodscan/modbusmessages/getcommeventlog.h index ce391f7..b10425f 100644 --- a/omodscan/modbusmessages/getcommeventlog.h +++ b/omodscan/modbusmessages/getcommeventlog.h @@ -12,11 +12,12 @@ class GetCommEventLogRequest : public ModbusMessage /// /// \brief GetCommEventLogRequest /// \param pdu - /// \param timestamp + /// \param protocol /// \param deviceId + /// \param timestamp /// - GetCommEventLogRequest(const QModbusPdu& pdu, const QDateTime& timestamp, int deviceId) - : ModbusMessage(pdu, timestamp, deviceId, true) + GetCommEventLogRequest(const QModbusPdu& pdu, QModbusAdu::Type protocol, int deviceId, const QDateTime& timestamp) + : ModbusMessage(pdu, protocol, deviceId, timestamp, true) { Q_ASSERT(functionCode() == QModbusPdu::GetCommEventLog); } @@ -42,11 +43,12 @@ class GetCommEventLogResponse : public ModbusMessage /// /// \brief GetCommEventLogResponse /// \param pdu - /// \param timestamp + /// \param protocol /// \param deviceId + /// \param timestamp /// - GetCommEventLogResponse(const QModbusPdu& pdu, const QDateTime& timestamp, int deviceId) - :ModbusMessage(pdu, timestamp, deviceId, false) + GetCommEventLogResponse(const QModbusPdu& pdu, QModbusAdu::Type protocol, int deviceId, const QDateTime& timestamp) + :ModbusMessage(pdu, protocol, deviceId, timestamp, false) { Q_ASSERT(functionCode() == QModbusPdu::GetCommEventLog); } @@ -67,7 +69,9 @@ class GetCommEventLogResponse : public ModbusMessage /// \return /// bool isValid() const override { - return ModbusMessage::isValid() && dataSize() > 7; + return ModbusMessage::isValid() && + byteCount() > 0 && + byteCount() == events().size() - 6; } /// diff --git a/omodscan/modbusmessages/maskwriteregister.h b/omodscan/modbusmessages/maskwriteregister.h index f388b1a..05a11ec 100644 --- a/omodscan/modbusmessages/maskwriteregister.h +++ b/omodscan/modbusmessages/maskwriteregister.h @@ -12,11 +12,12 @@ class MaskWriteRegisterRequest : public ModbusMessage /// /// \brief MaskWriteRegisterRequest /// \param pdu - /// \param timestamp + /// \param protocol /// \param deviceId + /// \param timestamp /// - MaskWriteRegisterRequest(const QModbusPdu& pdu, const QDateTime& timestamp, int deviceId) - : ModbusMessage(pdu, timestamp, deviceId, true) + MaskWriteRegisterRequest(const QModbusPdu& pdu, QModbusAdu::Type protocol, int deviceId, const QDateTime& timestamp) + : ModbusMessage(pdu, protocol, deviceId, timestamp, true) { Q_ASSERT(functionCode() == QModbusPdu::MaskWriteRegister); } @@ -74,11 +75,12 @@ class MaskWriteRegisterResponse : public ModbusMessage /// /// \brief MaskWriteRegisterResponse /// \param pdu - /// \param timestamp + /// \param protocol /// \param deviceId + /// \param timestamp /// - MaskWriteRegisterResponse(const QModbusPdu& pdu, const QDateTime& timestamp, int deviceId) - :ModbusMessage(pdu, timestamp, deviceId, false) + MaskWriteRegisterResponse(const QModbusPdu& pdu, QModbusAdu::Type protocol, int deviceId, const QDateTime& timestamp) + :ModbusMessage(pdu, protocol, deviceId, timestamp, false) { Q_ASSERT(functionCode() == QModbusPdu::MaskWriteRegister); } diff --git a/omodscan/modbusmessages/modbusmessage.cpp b/omodscan/modbusmessages/modbusmessage.cpp index 983982d..5b1d043 100644 --- a/omodscan/modbusmessages/modbusmessage.cpp +++ b/omodscan/modbusmessages/modbusmessage.cpp @@ -4,89 +4,90 @@ /// /// \brief ModbusMessage::create /// \param pdu -/// \param timestamp +/// \param protocol /// \param deviceId +/// \param timestamp /// \param request /// \return /// -const ModbusMessage* ModbusMessage::create(const QModbusPdu& pdu, const QDateTime& timestamp, int deviceId, bool request) +const ModbusMessage* ModbusMessage::create(const QModbusPdu& pdu, QModbusAdu::Type protocol, int deviceId, const QDateTime& timestamp, bool request) { switch(pdu.functionCode()) { case QModbusPdu::ReadCoils: - if(request) return new ReadCoilsRequest(pdu, timestamp, deviceId); - else return new ReadCoilsResponse(pdu, timestamp, deviceId); + if(request) return new ReadCoilsRequest(pdu, protocol, deviceId, timestamp); + else return new ReadCoilsResponse(pdu, protocol, deviceId, timestamp); case QModbusPdu::ReadDiscreteInputs: - if(request) return new ReadDiscreteInputsRequest(pdu, timestamp, deviceId); - else return new ReadDiscreteInputsResponse(pdu, timestamp, deviceId); + if(request) return new ReadDiscreteInputsRequest(pdu, protocol, deviceId, timestamp); + else return new ReadDiscreteInputsResponse(pdu, protocol, deviceId, timestamp); case QModbusPdu::ReadHoldingRegisters: - if(request) return new ReadHoldingRegistersRequest(pdu, timestamp, deviceId); - else return new ReadHoldingRegistersResponse(pdu, timestamp, deviceId); + if(request) return new ReadHoldingRegistersRequest(pdu, protocol, deviceId, timestamp); + else return new ReadHoldingRegistersResponse(pdu, protocol, deviceId, timestamp); case QModbusPdu::ReadInputRegisters: - if(request) return new ReadInputRegistersRequest(pdu, timestamp, deviceId); - else return new ReadInputRegistersResponse(pdu, timestamp, deviceId); + if(request) return new ReadInputRegistersRequest(pdu, protocol, deviceId, timestamp); + else return new ReadInputRegistersResponse(pdu, protocol, deviceId, timestamp); case QModbusPdu::WriteSingleCoil: - if(request) return new WriteSingleCoilRequest(pdu, timestamp, deviceId); - else return new WriteSingleCoilResponse(pdu, timestamp, deviceId); + if(request) return new WriteSingleCoilRequest(pdu, protocol, deviceId, timestamp); + else return new WriteSingleCoilResponse(pdu, protocol, deviceId, timestamp); case QModbusPdu::WriteSingleRegister: - if(request) return new WriteSingleRegisterRequest(pdu, timestamp, deviceId); - else return new WriteSingleRegisterResponse(pdu, timestamp, deviceId); + if(request) return new WriteSingleRegisterRequest(pdu, protocol, deviceId, timestamp); + else return new WriteSingleRegisterResponse(pdu, protocol, deviceId, timestamp); case QModbusPdu::ReadExceptionStatus: - if(request) return new ReadExceptionStatusRequest(pdu, timestamp, deviceId); - else return new ReadExceptionStatusResponse(pdu, timestamp, deviceId); + if(request) return new ReadExceptionStatusRequest(pdu, protocol, deviceId, timestamp); + else return new ReadExceptionStatusResponse(pdu, protocol, deviceId, timestamp); case QModbusPdu::Diagnostics: - if(request) return new DiagnosticsRequest(pdu, timestamp, deviceId); - else return new DiagnosticsResponse(pdu, timestamp, deviceId); + if(request) return new DiagnosticsRequest(pdu, protocol, deviceId, timestamp); + else return new DiagnosticsResponse(pdu, protocol, deviceId, timestamp); case QModbusPdu::GetCommEventCounter: - if(request) return new GetCommEventCounterRequest(pdu, timestamp, deviceId); - else return new GetCommEventCounterResponse(pdu, timestamp, deviceId); + if(request) return new GetCommEventCounterRequest(pdu, protocol, deviceId, timestamp); + else return new GetCommEventCounterResponse(pdu, protocol, deviceId, timestamp); case QModbusPdu::GetCommEventLog: - if(request) return new GetCommEventLogRequest(pdu, timestamp, deviceId); - else return new GetCommEventLogResponse(pdu, timestamp, deviceId); + if(request) return new GetCommEventLogRequest(pdu, protocol, deviceId, timestamp); + else return new GetCommEventLogResponse(pdu, protocol, deviceId, timestamp); case QModbusPdu::WriteMultipleCoils: - if(request) return new WriteMultipleCoilsRequest(pdu, timestamp, deviceId); - else return new WriteMultipleCoilsResponse(pdu, timestamp, deviceId); + if(request) return new WriteMultipleCoilsRequest(pdu, protocol, deviceId, timestamp); + else return new WriteMultipleCoilsResponse(pdu, protocol, deviceId, timestamp); case QModbusPdu::WriteMultipleRegisters: - if(request) return new WriteMultipleRegistersRequest(pdu, timestamp, deviceId); - else return new WriteMultipleRegistersResponse(pdu, timestamp, deviceId); + if(request) return new WriteMultipleRegistersRequest(pdu, protocol, deviceId, timestamp); + else return new WriteMultipleRegistersResponse(pdu, protocol, deviceId, timestamp); case QModbusPdu::ReportServerId: - if(request) return new ReportServerIdRequest(pdu, timestamp, deviceId); - else return new ReportServerIdResponse(pdu, timestamp, deviceId); + if(request) return new ReportServerIdRequest(pdu, protocol, deviceId, timestamp); + else return new ReportServerIdResponse(pdu, protocol, deviceId, timestamp); case QModbusPdu::ReadFileRecord: - if(request) return new ReadFileRecordRequest(pdu, timestamp, deviceId); - else return new ReadFileRecordResponse(pdu, timestamp, deviceId); + if(request) return new ReadFileRecordRequest(pdu, protocol, deviceId, timestamp); + else return new ReadFileRecordResponse(pdu, protocol, deviceId, timestamp); case QModbusPdu::WriteFileRecord: - if(request) return new WriteFileRecordRequest(pdu, timestamp, deviceId); - else return new WriteFileRecordResponse(pdu, timestamp, deviceId); + if(request) return new WriteFileRecordRequest(pdu, protocol, deviceId, timestamp); + else return new WriteFileRecordResponse(pdu, protocol, deviceId, timestamp); case QModbusPdu::MaskWriteRegister: - if(request) return new MaskWriteRegisterRequest(pdu, timestamp, deviceId); - else return new MaskWriteRegisterResponse(pdu, timestamp, deviceId); + if(request) return new MaskWriteRegisterRequest(pdu, protocol, deviceId, timestamp); + else return new MaskWriteRegisterResponse(pdu, protocol, deviceId, timestamp); case QModbusPdu::ReadWriteMultipleRegisters: - if(request) return new ReadWriteMultipleRegistersRequest(pdu, timestamp, deviceId); - else return new ReadWriteMultipleRegistersResponse(pdu, timestamp, deviceId); + if(request) return new ReadWriteMultipleRegistersRequest(pdu, protocol, deviceId, timestamp); + else return new ReadWriteMultipleRegistersResponse(pdu, protocol, deviceId, timestamp); case QModbusPdu::ReadFifoQueue: - if(request) return new ReadFifoQueueRequest(pdu, timestamp, deviceId); - else return new ReadFifoQueueResponse(pdu, timestamp, deviceId); + if(request) return new ReadFifoQueueRequest(pdu, protocol, deviceId, timestamp); + else return new ReadFifoQueueResponse(pdu, protocol, deviceId, timestamp); default: - return new ModbusMessage(pdu, timestamp, deviceId, request); + return new ModbusMessage(pdu, protocol, deviceId, timestamp, request); } } @@ -200,9 +201,19 @@ const ModbusMessage* ModbusMessage::parse(const QByteArray& data, Type type, QMo { QModbusPdu pdu; pdu.setFunctionCode((QModbusPdu::FunctionCode)data[1]); - pdu.setData(data.mid(2, data.size() - 2)); - return create(pdu, QDateTime::currentDateTime(), data[0], request); + switch(protocol) + { + case QModbusAdu::Tcp: + pdu.setData(data.mid(2, data.size() - 2)); + break; + + case QModbusAdu::Rtu: + pdu.setData(data.mid(2, data.size() - 4)); + break; + } + + return create(pdu, protocol, data[0], QDateTime::currentDateTime(), request); } default: diff --git a/omodscan/modbusmessages/modbusmessage.h b/omodscan/modbusmessages/modbusmessage.h index 165ba9a..2e2ce24 100644 --- a/omodscan/modbusmessages/modbusmessage.h +++ b/omodscan/modbusmessages/modbusmessage.h @@ -22,12 +22,14 @@ class ModbusMessage /// /// \brief ModbusMessage /// \param pdu - /// \param timestamp + /// \param protocol /// \param deviceId + /// \param timestamp /// \param request /// - explicit ModbusMessage(const QModbusPdu& pdu, const QDateTime& timestamp, int deviceId, bool request) + explicit ModbusMessage(const QModbusPdu& pdu, QModbusAdu::Type protocol, int deviceId, const QDateTime& timestamp, bool request) :_type(Type::Pdu) + ,_protocol(protocol) ,_data(pdu.data()) ,_funcCode(pdu.isException() ? (pdu.functionCode() | QModbusPdu::ExceptionByte) : pdu.functionCode()) ,_exceptionCode(pdu.exceptionCode()) @@ -38,6 +40,7 @@ class ModbusMessage ,_deviceId(deviceId) ,_request(request) ,_isValid(pdu.isValid()) + ,_checksum(calcCRC(pdu, deviceId)) { } @@ -49,6 +52,7 @@ class ModbusMessage /// explicit ModbusMessage(const QModbusAdu& adu, const QDateTime& timestamp, bool request) :_type(Type::Adu) + ,_protocol(adu.type()) ,_data(adu.data()) ,_funcCode(adu.isException() ? (adu.functionCode() | QModbusPdu::ExceptionByte) : adu.functionCode()) ,_exceptionCode(adu.exceptionCode()) @@ -59,6 +63,7 @@ class ModbusMessage ,_deviceId(adu.serverAddress()) ,_request(request) ,_isValid(adu.isValid()) + ,_checksum(adu.checksum()) { } @@ -70,12 +75,13 @@ class ModbusMessage /// /// \brief create /// \param pdu - /// \param timestamp + /// \param protocol /// \param deviceId + /// \param timestamp /// \param request /// \return /// - static const ModbusMessage* create(const QModbusPdu& pdu, const QDateTime& timestamp, int deviceId, bool request); + static const ModbusMessage* create(const QModbusPdu& pdu, QModbusAdu::Type protocol, int deviceId, const QDateTime& timestamp, bool request); /// /// \brief create @@ -120,6 +126,14 @@ class ModbusMessage return _protocolId; } + /// + /// \brief protocolType + /// \return + /// + QModbusAdu::Type protocolType() const { + return _protocol; + } + /// /// \brief length /// \return @@ -210,6 +224,14 @@ class ModbusMessage return _data; } + /// + /// \brief checksum + /// \return + /// + int checksum() const { + return _checksum; + } + /// /// \brief operator QByteArray /// @@ -268,8 +290,22 @@ class ModbusMessage return 0; } +private: + int calcCRC(const QModbusPdu& pdu, int deviceId) { + if(_protocol != QModbusAdu::Rtu) + return 0; + + QByteArray data; + data.push_back(deviceId); + data.push_back(pdu.functionCode()); + data.push_back(pdu.data()); + qDebug() << formatByteArray(DataDisplayMode::Hex, data); + return QModbusAdu::calculateCRC(data, data.length()); + } + private: const Type _type; + QModbusAdu::Type _protocol; const QByteArray _data; const quint8 _funcCode; const quint8 _exceptionCode; @@ -280,6 +316,7 @@ class ModbusMessage const int _deviceId; const bool _request; const bool _isValid; + const int _checksum; }; Q_DECLARE_METATYPE(const ModbusMessage*) diff --git a/omodscan/modbusmessages/readcoils.h b/omodscan/modbusmessages/readcoils.h index 3e2bcf0..04e7484 100644 --- a/omodscan/modbusmessages/readcoils.h +++ b/omodscan/modbusmessages/readcoils.h @@ -13,11 +13,12 @@ class ReadCoilsRequest : public ModbusMessage /// /// \brief ReadCoilsRequest /// \param pdu - /// \param timestamp + /// \param protocol /// \param deviceId + /// \param timestamp /// - ReadCoilsRequest(const QModbusPdu& pdu, const QDateTime& timestamp, int deviceId) - : ModbusMessage(pdu, timestamp, deviceId, true) + ReadCoilsRequest(const QModbusPdu& pdu, QModbusAdu::Type protocol, int deviceId, const QDateTime& timestamp) + : ModbusMessage(pdu, protocol, deviceId, timestamp, true) { Q_ASSERT(functionCode() == QModbusPdu::ReadCoils); } @@ -38,7 +39,8 @@ class ReadCoilsRequest : public ModbusMessage /// \return /// bool isValid() const override { - return ModbusMessage::isValid() && dataSize() == 4; + return ModbusMessage::isValid() && + length() >= 1 && length() <= 0x7D0; } /// @@ -67,11 +69,12 @@ class ReadCoilsResponse : public ModbusMessage /// /// \brief ReadCoilsResponse /// \param pdu - /// \param timestamp + /// \param protocol /// \param deviceId + /// \param timestamp /// - ReadCoilsResponse(const QModbusPdu& pdu, const QDateTime& timestamp, int deviceId) - :ModbusMessage(pdu, timestamp, deviceId, false) + ReadCoilsResponse(const QModbusPdu& pdu, QModbusAdu::Type protocol, int deviceId, const QDateTime& timestamp) + :ModbusMessage(pdu, protocol, deviceId, timestamp, false) { Q_ASSERT(functionCode() == QModbusPdu::ReadCoils); } @@ -92,7 +95,9 @@ class ReadCoilsResponse : public ModbusMessage /// \return /// bool isValid() const override { - return ModbusMessage::isValid() && dataSize() > 1; + return ModbusMessage::isValid() && + byteCount() > 0 && + (byteCount() == coilStatus().size() || byteCount() == coilStatus().size() - 1); } /// diff --git a/omodscan/modbusmessages/readdiscreteinputs.h b/omodscan/modbusmessages/readdiscreteinputs.h index 1ae993f..0f83bd4 100644 --- a/omodscan/modbusmessages/readdiscreteinputs.h +++ b/omodscan/modbusmessages/readdiscreteinputs.h @@ -12,11 +12,12 @@ class ReadDiscreteInputsRequest : public ModbusMessage /// /// \brief ReadDiscreteInputsRequest /// \param pdu - /// \param timestamp + /// \param protocol /// \param deviceId + /// \param timestamp /// - ReadDiscreteInputsRequest(const QModbusPdu& pdu, const QDateTime& timestamp, int deviceId) - : ModbusMessage(pdu, timestamp, deviceId, true) + ReadDiscreteInputsRequest(const QModbusPdu& pdu, QModbusAdu::Type protocol, int deviceId, const QDateTime& timestamp) + : ModbusMessage(pdu, protocol, deviceId, timestamp, true) { Q_ASSERT(functionCode() == QModbusPdu::ReadDiscreteInputs); } @@ -37,7 +38,8 @@ class ReadDiscreteInputsRequest : public ModbusMessage /// \return /// bool isValid() const override { - return ModbusMessage::isValid() && dataSize() == 4; + return ModbusMessage::isValid() && + length() >= 1 && length() <= 0x7D0; } /// @@ -66,11 +68,12 @@ class ReadDiscreteInputsResponse : public ModbusMessage /// /// \brief ReadDiscreteInputsResponse /// \param pdu - /// \param timestamp + /// \param protocol /// \param deviceId + /// \param timestamp /// - ReadDiscreteInputsResponse(const QModbusPdu& pdu, const QDateTime& timestamp, int deviceId) - :ModbusMessage(pdu, timestamp, deviceId, false) + ReadDiscreteInputsResponse(const QModbusPdu& pdu, QModbusAdu::Type protocol, int deviceId, const QDateTime& timestamp) + :ModbusMessage(pdu, protocol, deviceId, timestamp, false) { Q_ASSERT(functionCode() == QModbusPdu::ReadDiscreteInputs); } @@ -91,7 +94,9 @@ class ReadDiscreteInputsResponse : public ModbusMessage /// \return /// bool isValid() const override { - return ModbusMessage::isValid() && dataSize() > 1; + return ModbusMessage::isValid() && + byteCount() > 0 && + (byteCount() == inputStatus().size() || byteCount() == inputStatus().size() - 1); } /// diff --git a/omodscan/modbusmessages/readexceptionstatus.h b/omodscan/modbusmessages/readexceptionstatus.h index 4a760da..8c73ee0 100644 --- a/omodscan/modbusmessages/readexceptionstatus.h +++ b/omodscan/modbusmessages/readexceptionstatus.h @@ -12,11 +12,12 @@ class ReadExceptionStatusRequest : public ModbusMessage /// /// \brief ReadExceptionStatusRequest /// \param pdu - /// \param timestamp + /// \param protocol /// \param deviceId + /// \param timestamp /// - ReadExceptionStatusRequest(const QModbusPdu& pdu, const QDateTime& timestamp, int deviceId) - : ModbusMessage(pdu, timestamp, deviceId, true) + ReadExceptionStatusRequest(const QModbusPdu& pdu, QModbusAdu::Type protocol, int deviceId, const QDateTime& timestamp) + : ModbusMessage(pdu, protocol, deviceId, timestamp, true) { Q_ASSERT(functionCode() == QModbusPdu::ReadExceptionStatus); } @@ -42,11 +43,12 @@ class ReadExceptionStatusResponse : public ModbusMessage /// /// \brief ReadExceptionStatusResponse /// \param pdu - /// \param timestamp + /// \param protocol /// \param deviceId + /// \param timestamp /// - ReadExceptionStatusResponse(const QModbusPdu& pdu, const QDateTime& timestamp, int deviceId) - :ModbusMessage(pdu, timestamp, deviceId, false) + ReadExceptionStatusResponse(const QModbusPdu& pdu, QModbusAdu::Type protocol, int deviceId, const QDateTime& timestamp) + :ModbusMessage(pdu, protocol, deviceId, timestamp, false) { Q_ASSERT(functionCode() == QModbusPdu::ReadExceptionStatus); } diff --git a/omodscan/modbusmessages/readfifoqueue.h b/omodscan/modbusmessages/readfifoqueue.h index 1fbdb2d..73dd838 100644 --- a/omodscan/modbusmessages/readfifoqueue.h +++ b/omodscan/modbusmessages/readfifoqueue.h @@ -12,11 +12,12 @@ class ReadFifoQueueRequest : public ModbusMessage /// /// \brief ReadFifoQueueRequest /// \param pdu - /// \param timestamp + /// \param protocol /// \param deviceId + /// \param timestamp /// - ReadFifoQueueRequest(const QModbusPdu& pdu, const QDateTime& timestamp, int deviceId) - : ModbusMessage(pdu, timestamp, deviceId, true) + ReadFifoQueueRequest(const QModbusPdu& pdu, QModbusAdu::Type protocol, int deviceId, const QDateTime& timestamp) + : ModbusMessage(pdu, protocol, deviceId, timestamp, true) { Q_ASSERT(functionCode() == QModbusPdu::ReadFifoQueue); } @@ -58,11 +59,12 @@ class ReadFifoQueueResponse : public ModbusMessage /// /// \brief ReadFifoQueueResponse /// \param pdu - /// \param timestamp + /// \param protocol /// \param deviceId + /// \param timestamp /// - ReadFifoQueueResponse(const QModbusPdu& pdu, const QDateTime& timestamp, int deviceId) - :ModbusMessage(pdu, timestamp, deviceId, false) + ReadFifoQueueResponse(const QModbusPdu& pdu, QModbusAdu::Type protocol, int deviceId, const QDateTime& timestamp) + :ModbusMessage(pdu, protocol, deviceId, timestamp, false) { Q_ASSERT(functionCode() == QModbusPdu::ReadFifoQueue); } @@ -83,7 +85,9 @@ class ReadFifoQueueResponse : public ModbusMessage /// \return /// bool isValid() const override { - return ModbusMessage::isValid() && dataSize() > 5; + return ModbusMessage::isValid() && + fifoCount() <= 31 && + fifoCount() == fifoValue().size(); } /// diff --git a/omodscan/modbusmessages/readfilerecord.h b/omodscan/modbusmessages/readfilerecord.h index e5c3d89..ce5c916 100644 --- a/omodscan/modbusmessages/readfilerecord.h +++ b/omodscan/modbusmessages/readfilerecord.h @@ -12,11 +12,12 @@ class ReadFileRecordRequest : public ModbusMessage /// /// \brief ReadFileRecordRequest /// \param pdu - /// \param timestamp + /// \param protocol /// \param deviceId + /// \param timestamp /// - ReadFileRecordRequest(const QModbusPdu& pdu, const QDateTime& timestamp, int deviceId) - : ModbusMessage(pdu, timestamp, deviceId, true) + ReadFileRecordRequest(const QModbusPdu& pdu, QModbusAdu::Type protocol, int deviceId, const QDateTime& timestamp) + : ModbusMessage(pdu, protocol, deviceId, timestamp, true) { Q_ASSERT(functionCode() == QModbusPdu::ReadFileRecord); } @@ -37,7 +38,8 @@ class ReadFileRecordRequest : public ModbusMessage /// \return /// bool isValid() const override { - return ModbusMessage::isValid() && dataSize() > 1; + return ModbusMessage::isValid() && + byteCount() >= 0x07 && byteCount() <= 0xF5; } /// @@ -66,11 +68,12 @@ class ReadFileRecordResponse : public ModbusMessage /// /// \brief ReadFileRecordResponse /// \param pdu - /// \param timestamp + /// \param protocol /// \param deviceId + /// \param timestamp /// - ReadFileRecordResponse(const QModbusPdu& pdu, const QDateTime& timestamp, int deviceId) - :ModbusMessage(pdu, timestamp, deviceId, false) + ReadFileRecordResponse(const QModbusPdu& pdu, QModbusAdu::Type protocol, int deviceId, const QDateTime& timestamp) + :ModbusMessage(pdu, protocol, deviceId, timestamp, false) { Q_ASSERT(functionCode() == QModbusPdu::ReadFileRecord); } @@ -91,7 +94,8 @@ class ReadFileRecordResponse : public ModbusMessage /// \return /// bool isValid() const override { - return ModbusMessage::isValid() && dataSize() > 1; + return ModbusMessage::isValid() && + byteCount() >= 0x07 && byteCount() <= 0xF5;; } /// diff --git a/omodscan/modbusmessages/readholdingregisters.h b/omodscan/modbusmessages/readholdingregisters.h index 9dba4ff..4a2fe25 100644 --- a/omodscan/modbusmessages/readholdingregisters.h +++ b/omodscan/modbusmessages/readholdingregisters.h @@ -12,11 +12,12 @@ class ReadHoldingRegistersRequest : public ModbusMessage /// /// \brief ReadHoldingRegistersRequest /// \param pdu - /// \param timestamp + /// \param protocol /// \param deviceId + /// \param timestamp /// - ReadHoldingRegistersRequest(const QModbusPdu& pdu, const QDateTime& timestamp, int deviceId) - : ModbusMessage(pdu, timestamp, deviceId, true) + ReadHoldingRegistersRequest(const QModbusPdu& pdu, QModbusAdu::Type protocol, int deviceId, const QDateTime& timestamp) + : ModbusMessage(pdu, protocol, deviceId, timestamp, true) { Q_ASSERT(functionCode() == QModbusPdu::ReadHoldingRegisters); } @@ -37,7 +38,8 @@ class ReadHoldingRegistersRequest : public ModbusMessage /// \return /// bool isValid() const override { - return ModbusMessage::isValid() && dataSize() == 4; + return ModbusMessage::isValid() && + length() >= 1 && length() <= 0x7D; } /// @@ -66,11 +68,12 @@ class ReadHoldingRegistersResponse : public ModbusMessage /// /// \brief ReadHoldingRegistersResponse /// \param pdu - /// \param timestamp + /// \param protocol /// \param deviceId + /// \param timestamp /// - ReadHoldingRegistersResponse(const QModbusPdu& pdu, const QDateTime& timestamp, int deviceId) - :ModbusMessage(pdu, timestamp, deviceId, false) + ReadHoldingRegistersResponse(const QModbusPdu& pdu, QModbusAdu::Type protocol, int deviceId, const QDateTime& timestamp) + :ModbusMessage(pdu, protocol, deviceId, timestamp, false) { Q_ASSERT(functionCode() == QModbusPdu::ReadHoldingRegisters); } @@ -91,7 +94,9 @@ class ReadHoldingRegistersResponse : public ModbusMessage /// \return /// bool isValid() const override { - return ModbusMessage::isValid() && dataSize() > 1; + return ModbusMessage::isValid() && + byteCount() > 0 && + byteCount() == registerValue().size(); } /// diff --git a/omodscan/modbusmessages/readinputregisters.h b/omodscan/modbusmessages/readinputregisters.h index c444cf5..92a1b55 100644 --- a/omodscan/modbusmessages/readinputregisters.h +++ b/omodscan/modbusmessages/readinputregisters.h @@ -12,11 +12,12 @@ class ReadInputRegistersRequest : public ModbusMessage /// /// \brief ReadInputRegistersRequest /// \param pdu - /// \param timestamp + /// \param protocol /// \param deviceId + /// \param timestamp /// - ReadInputRegistersRequest(const QModbusPdu& pdu, const QDateTime& timestamp, int deviceId) - : ModbusMessage(pdu, timestamp, deviceId, true) + ReadInputRegistersRequest(const QModbusPdu& pdu, QModbusAdu::Type protocol, int deviceId, const QDateTime& timestamp) + : ModbusMessage(pdu, protocol, deviceId, timestamp, true) { Q_ASSERT(functionCode() == QModbusPdu::ReadInputRegisters); } @@ -37,7 +38,8 @@ class ReadInputRegistersRequest : public ModbusMessage /// \return /// bool isValid() const override { - return ModbusMessage::isValid() && dataSize() == 4; + return ModbusMessage::isValid() && + length() >= 1 && length() <= 0x7D; } /// @@ -66,11 +68,12 @@ class ReadInputRegistersResponse : public ModbusMessage /// /// \brief ReadInputRegistersResponse /// \param pdu - /// \param timestamp + /// \param protocol /// \param deviceId + /// \param timestamp /// - ReadInputRegistersResponse(const QModbusPdu& pdu, const QDateTime& timestamp, int deviceId) - :ModbusMessage(pdu, timestamp, deviceId, false) + ReadInputRegistersResponse(const QModbusPdu& pdu, QModbusAdu::Type protocol, int deviceId, const QDateTime& timestamp) + :ModbusMessage(pdu, protocol, deviceId, timestamp, false) { Q_ASSERT(functionCode() == QModbusPdu::ReadInputRegisters); } @@ -91,7 +94,9 @@ class ReadInputRegistersResponse : public ModbusMessage /// \return /// bool isValid() const override { - return ModbusMessage::isValid() && dataSize() > 1; + return ModbusMessage::isValid() && + byteCount() > 0 && + byteCount() == registerValue().size(); } /// diff --git a/omodscan/modbusmessages/readwritemultipleregisters.h b/omodscan/modbusmessages/readwritemultipleregisters.h index 3b50f4c..d32d274 100644 --- a/omodscan/modbusmessages/readwritemultipleregisters.h +++ b/omodscan/modbusmessages/readwritemultipleregisters.h @@ -12,11 +12,12 @@ class ReadWriteMultipleRegistersRequest : public ModbusMessage /// /// \brief ReadWriteMultipleRegistersRequest /// \param pdu - /// \param timestamp + /// \param protocol /// \param deviceId + /// \param timestamp /// - ReadWriteMultipleRegistersRequest(const QModbusPdu& pdu, const QDateTime& timestamp, int deviceId) - : ModbusMessage(pdu, timestamp, deviceId, true) + ReadWriteMultipleRegistersRequest(const QModbusPdu& pdu, QModbusAdu::Type protocol, int deviceId, const QDateTime& timestamp) + : ModbusMessage(pdu, protocol, deviceId, timestamp, true) { Q_ASSERT(functionCode() == QModbusPdu::ReadWriteMultipleRegisters); } @@ -37,7 +38,11 @@ class ReadWriteMultipleRegistersRequest : public ModbusMessage /// \return /// bool isValid() const override { - return ModbusMessage::isValid() && dataSize() > 9; + return ModbusMessage::isValid() && + readLength() >= 1 && readLength() <= 0x7D && + writeLength() >= 1 && writeLength() <= 0x79 && + writeByteCount() > 0 && + writeByteCount() == writeValues().size(); } /// @@ -98,11 +103,12 @@ class ReadWriteMultipleRegistersResponse : public ModbusMessage /// /// \brief ReadWriteMultipleRegistersResponse /// \param pdu - /// \param timestamp + /// \param protocol /// \param deviceId + /// \param timestamp /// - ReadWriteMultipleRegistersResponse(const QModbusPdu& pdu, const QDateTime& timestamp, int deviceId) - :ModbusMessage(pdu, timestamp, deviceId, false) + ReadWriteMultipleRegistersResponse(const QModbusPdu& pdu, QModbusAdu::Type protocol, int deviceId, const QDateTime& timestamp) + :ModbusMessage(pdu, protocol, deviceId, timestamp, false) { Q_ASSERT(functionCode() == QModbusPdu::ReadWriteMultipleRegisters); } @@ -123,7 +129,9 @@ class ReadWriteMultipleRegistersResponse : public ModbusMessage /// \return /// bool isValid() const override { - return ModbusMessage::isValid() && dataSize() > 1; + return ModbusMessage::isValid() && + byteCount() > 0 && + byteCount() == values().size(); } /// diff --git a/omodscan/modbusmessages/reportserverid.h b/omodscan/modbusmessages/reportserverid.h index a358647..17b6b1e 100644 --- a/omodscan/modbusmessages/reportserverid.h +++ b/omodscan/modbusmessages/reportserverid.h @@ -12,11 +12,12 @@ class ReportServerIdRequest : public ModbusMessage /// /// \brief ReportServerIdRequest /// \param pdu - /// \param timestamp + /// \param protocol /// \param deviceId + /// \param timestamp /// - ReportServerIdRequest(const QModbusPdu& pdu, const QDateTime& timestamp, int deviceId) - : ModbusMessage(pdu, timestamp, deviceId, true) + ReportServerIdRequest(const QModbusPdu& pdu, QModbusAdu::Type protocol, int deviceId, const QDateTime& timestamp) + : ModbusMessage(pdu, protocol, deviceId, timestamp, true) { Q_ASSERT(functionCode() == QModbusPdu::ReportServerId); } @@ -42,11 +43,12 @@ class ReportServerIdResponse : public ModbusMessage /// /// \brief ReportServerIdResponse /// \param pdu - /// \param timestamp + /// \param protocol /// \param deviceId + /// \param timestamp /// - ReportServerIdResponse(const QModbusPdu& pdu, const QDateTime& timestamp, int deviceId) - :ModbusMessage(pdu, timestamp, deviceId, false) + ReportServerIdResponse(const QModbusPdu& pdu, QModbusAdu::Type protocol, int deviceId, const QDateTime& timestamp) + :ModbusMessage(pdu, protocol, deviceId, timestamp, false) { Q_ASSERT(functionCode() == QModbusPdu::ReportServerId); } diff --git a/omodscan/modbusmessages/writefilerecord.h b/omodscan/modbusmessages/writefilerecord.h index beb3c44..3be7ceb 100644 --- a/omodscan/modbusmessages/writefilerecord.h +++ b/omodscan/modbusmessages/writefilerecord.h @@ -12,11 +12,12 @@ class WriteFileRecordRequest : public ModbusMessage /// /// \brief WriteFileRecordRequest /// \param pdu - /// \param timestamp + /// \param protocol /// \param deviceId + /// \param timestamp /// - WriteFileRecordRequest(const QModbusPdu& pdu, const QDateTime& timestamp, int deviceId) - : ModbusMessage(pdu, timestamp, deviceId, true) + WriteFileRecordRequest(const QModbusPdu& pdu, QModbusAdu::Type protocol, int deviceId, const QDateTime& timestamp) + : ModbusMessage(pdu, protocol, deviceId, timestamp, true) { Q_ASSERT(functionCode() == QModbusPdu::WriteFileRecord); } @@ -37,7 +38,9 @@ class WriteFileRecordRequest : public ModbusMessage /// \return /// bool isValid() const override { - return ModbusMessage::isValid() && dataSize() > 1; + return ModbusMessage::isValid() && + length() >= 0x09 && + length() <= 0xFB; } /// @@ -66,11 +69,12 @@ class WriteFileRecordResponse : public ModbusMessage /// /// \brief WriteFileRecordResponse /// \param pdu - /// \param timestamp + /// \param protocol /// \param deviceId + /// \param timestamp /// - WriteFileRecordResponse(const QModbusPdu& pdu, const QDateTime& timestamp, int deviceId) - :ModbusMessage(pdu, timestamp, deviceId, false) + WriteFileRecordResponse(const QModbusPdu& pdu, QModbusAdu::Type protocol, int deviceId, const QDateTime& timestamp) + :ModbusMessage(pdu, protocol, deviceId, timestamp, false) { Q_ASSERT(functionCode() == QModbusPdu::WriteFileRecord); } @@ -91,7 +95,9 @@ class WriteFileRecordResponse : public ModbusMessage /// \return /// bool isValid() const override { - return ModbusMessage::isValid() && dataSize() > 1; + return ModbusMessage::isValid() && + length() >= 0x09 && + length() <= 0xFB; } /// diff --git a/omodscan/modbusmessages/writemultiplecoils.h b/omodscan/modbusmessages/writemultiplecoils.h index 62ce370..8e36b4d 100644 --- a/omodscan/modbusmessages/writemultiplecoils.h +++ b/omodscan/modbusmessages/writemultiplecoils.h @@ -12,11 +12,12 @@ class WriteMultipleCoilsRequest : public ModbusMessage /// /// \brief WriteMultipleCoilsRequest /// \param pdu - /// \param timestamp + /// \param protocol /// \param deviceId + /// \param timestamp /// - WriteMultipleCoilsRequest(const QModbusPdu& pdu, const QDateTime& timestamp, int deviceId) - : ModbusMessage(pdu, timestamp, deviceId, true) + WriteMultipleCoilsRequest(const QModbusPdu& pdu, QModbusAdu::Type protocol, int deviceId, const QDateTime& timestamp) + : ModbusMessage(pdu, protocol, deviceId, timestamp, true) { Q_ASSERT(functionCode() == QModbusPdu::WriteMultipleCoils); } @@ -37,7 +38,9 @@ class WriteMultipleCoilsRequest : public ModbusMessage /// \return /// bool isValid() const override { - return ModbusMessage::isValid() && dataSize() > 5; + return ModbusMessage::isValid() && + byteCount() > 0 && + byteCount() == values().size(); } /// @@ -82,11 +85,12 @@ class WriteMultipleCoilsResponse : public ModbusMessage /// /// \brief WriteMultipleCoilsResponse /// \param pdu - /// \param timestamp + /// \param protocol /// \param deviceId + /// \param timestamp /// - WriteMultipleCoilsResponse(const QModbusPdu& pdu, const QDateTime& timestamp, int deviceId) - :ModbusMessage(pdu, timestamp, deviceId, false) + WriteMultipleCoilsResponse(const QModbusPdu& pdu, QModbusAdu::Type protocol, int deviceId, const QDateTime& timestamp) + :ModbusMessage(pdu, protocol, deviceId, timestamp, false) { Q_ASSERT(functionCode() == QModbusPdu::WriteMultipleCoils); } diff --git a/omodscan/modbusmessages/writemultipleregisters.h b/omodscan/modbusmessages/writemultipleregisters.h index 99cb478..90d0d91 100644 --- a/omodscan/modbusmessages/writemultipleregisters.h +++ b/omodscan/modbusmessages/writemultipleregisters.h @@ -12,11 +12,12 @@ class WriteMultipleRegistersRequest : public ModbusMessage /// /// \brief WriteMultipleRegistersRequest /// \param pdu - /// \param timestamp + /// \param protocol /// \param deviceId + /// \param timestamp /// - WriteMultipleRegistersRequest(const QModbusPdu& pdu, const QDateTime& timestamp, int deviceId) - : ModbusMessage(pdu, timestamp, deviceId, true) + WriteMultipleRegistersRequest(const QModbusPdu& pdu, QModbusAdu::Type protocol, int deviceId, const QDateTime& timestamp) + : ModbusMessage(pdu, protocol, deviceId, timestamp, true) { Q_ASSERT(functionCode() == QModbusPdu::WriteMultipleRegisters); } @@ -37,7 +38,9 @@ class WriteMultipleRegistersRequest : public ModbusMessage /// \return /// bool isValid() const override { - return ModbusMessage::isValid() && dataSize() > 5; + return ModbusMessage::isValid() && + byteCount() > 0 && + byteCount() == values().size(); } /// @@ -82,11 +85,12 @@ class WriteMultipleRegistersResponse : public ModbusMessage /// /// \brief WriteMultipleRegistersResponse /// \param pdu - /// \param timestamp + /// \param protocol /// \param deviceId + /// \param timestamp /// - WriteMultipleRegistersResponse(const QModbusPdu& pdu, const QDateTime& timestamp, int deviceId) - :ModbusMessage(pdu, timestamp, deviceId, false) + WriteMultipleRegistersResponse(const QModbusPdu& pdu, QModbusAdu::Type protocol, int deviceId, const QDateTime& timestamp) + :ModbusMessage(pdu, protocol, deviceId, timestamp, false) { Q_ASSERT(functionCode() == QModbusPdu::WriteMultipleRegisters); } diff --git a/omodscan/modbusmessages/writesinglecoil.h b/omodscan/modbusmessages/writesinglecoil.h index cfa90c8..4dae125 100644 --- a/omodscan/modbusmessages/writesinglecoil.h +++ b/omodscan/modbusmessages/writesinglecoil.h @@ -12,11 +12,12 @@ class WriteSingleCoilRequest : public ModbusMessage /// /// \brief WriteSingleCoilRequest /// \param pdu - /// \param timestamp + /// \param protocol /// \param deviceId + /// \param timestamp /// - WriteSingleCoilRequest(const QModbusPdu& pdu, const QDateTime& timestamp, int deviceId) - : ModbusMessage(pdu, timestamp, deviceId, true) + WriteSingleCoilRequest(const QModbusPdu& pdu, QModbusAdu::Type protocol, int deviceId, const QDateTime& timestamp) + : ModbusMessage(pdu, protocol, deviceId, timestamp, true) { Q_ASSERT(functionCode() == QModbusPdu::WriteSingleCoil); } @@ -37,7 +38,8 @@ class WriteSingleCoilRequest : public ModbusMessage /// \return /// bool isValid() const override { - return ModbusMessage::isValid() && dataSize() == 4; + return ModbusMessage::isValid() && + (value() == 0 || value() == 0xFF00); } /// @@ -66,11 +68,12 @@ class WriteSingleCoilResponse : public ModbusMessage /// /// \brief WriteSingleCoilResponse /// \param pdu - /// \param timestamp + /// \param protocol /// \param deviceId + /// \param timestamp /// - WriteSingleCoilResponse(const QModbusPdu& pdu, const QDateTime& timestamp, int deviceId) - :ModbusMessage(pdu, timestamp, deviceId, false) + WriteSingleCoilResponse(const QModbusPdu& pdu, QModbusAdu::Type protocol, int deviceId, const QDateTime& timestamp) + :ModbusMessage(pdu, protocol, deviceId, timestamp, false) { Q_ASSERT(functionCode() == QModbusPdu::WriteSingleCoil); } @@ -91,7 +94,8 @@ class WriteSingleCoilResponse : public ModbusMessage /// \return /// bool isValid() const override { - return ModbusMessage::isValid() && dataSize() == 4; + return ModbusMessage::isValid() && + (value() == 0 || value() == 0xFF00); } /// diff --git a/omodscan/modbusmessages/writesingleregister.h b/omodscan/modbusmessages/writesingleregister.h index 048ce36..9121dc7 100644 --- a/omodscan/modbusmessages/writesingleregister.h +++ b/omodscan/modbusmessages/writesingleregister.h @@ -12,11 +12,12 @@ class WriteSingleRegisterRequest : public ModbusMessage /// /// \brief WriteSingleRegisterRequest /// \param pdu - /// \param timestamp + /// \param protocol /// \param deviceId + /// \param timestamp /// - WriteSingleRegisterRequest(const QModbusPdu& pdu, const QDateTime& timestamp, int deviceId) - : ModbusMessage(pdu, timestamp, deviceId, true) + WriteSingleRegisterRequest(const QModbusPdu& pdu, QModbusAdu::Type protocol, int deviceId, const QDateTime& timestamp) + : ModbusMessage(pdu, protocol, deviceId, timestamp, true) { Q_ASSERT(functionCode() == QModbusPdu::WriteSingleRegister); } @@ -66,11 +67,12 @@ class WriteSingleRegisterResponse : public ModbusMessage /// /// \brief WriteSingleRegisterResponse /// \param pdu - /// \param timestamp + /// \param protocol /// \param deviceId + /// \param timestamp /// - WriteSingleRegisterResponse(const QModbusPdu& pdu, const QDateTime& timestamp, int deviceId) - :ModbusMessage(pdu, timestamp, deviceId, false) + WriteSingleRegisterResponse(const QModbusPdu& pdu, QModbusAdu::Type protocol, int deviceId, const QDateTime& timestamp) + :ModbusMessage(pdu, protocol, deviceId, timestamp, false) { Q_ASSERT(functionCode() == QModbusPdu::WriteSingleRegister); } diff --git a/omodscan/qmodbusadu.h b/omodscan/qmodbusadu.h index 65db306..6583607 100644 --- a/omodscan/qmodbusadu.h +++ b/omodscan/qmodbusadu.h @@ -24,6 +24,14 @@ class QModbusAdu setData(data); } + /// + /// \brief type + /// \return + /// + Type type() const { + return _type; + } + /// /// \brief isValid /// \return @@ -42,7 +50,15 @@ class QModbusAdu /// \brief setData /// \param data /// - void setData(const QByteArray& data) { _data = data; update(); } + void setData(const QByteArray& data) { + _data = data; + + _pdu.setFunctionCode(QModbusPdu::FunctionCode(_data[7])); + if(_type == Rtu) + _pdu.setData(_data.mid(8, _data.size() - 10)); + else + _pdu.setData(_data.mid(8)); + } /// /// \brief transactionId @@ -105,7 +121,9 @@ class QModbusAdu /// \return /// quint16 checksum() const { - return _type == Rtu ? quint16(quint8(_data[_data.size() - 2]) << 8 | quint8(_data[_data.size() - 1])) : quint16(0); + return _type == Rtu ? + makeWord(_data[_data.size() - 1], _data[_data.size() - 2], ByteOrder::LittleEndian) : + quint16(0); } /// @@ -122,17 +140,7 @@ class QModbusAdu return true; } -private: - void update() - { - _pdu.setFunctionCode(QModbusPdu::FunctionCode(_data[7])); - if(_type == Rtu) - _pdu.setData(_data.mid(8, _data.size() - 10)); - else - _pdu.setData(_data.mid(8)); - } - - inline static quint16 calculateCRC(const char *data, qint32 len){ + inline static quint16 calculateCRC(const char* data, qint32 len){ quint16 crc = 0xFFFF; while (len--) { const quint8 c = *data++; @@ -150,6 +158,7 @@ class QModbusAdu return (crc >> 8) | (crc << 8); // swap bytes } +private: inline static quint16 crc_reflect(quint16 data, qint32 len){ quint16 ret = data & 0x01; for (qint32 i = 1; i < len; i++) { From 54bf9d063257be592080a06b34d7585f32606914 Mon Sep 17 00:00:00 2001 From: sanny32 Date: Tue, 10 Oct 2023 15:48:44 +0300 Subject: [PATCH 69/90] Developing modbus message parser --- omodscan/controls/modbusmessagewidget.cpp | 20 +++- omodscan/dialogs/dialogmsgparser.cpp | 18 +++- omodscan/dialogs/dialogmsgparser.ui | 8 +- omodscan/modbusmessages/diagnostics.h | 10 +- omodscan/modbusmessages/getcommeventcounter.h | 10 +- omodscan/modbusmessages/getcommeventlog.h | 10 +- omodscan/modbusmessages/maskwriteregister.h | 10 +- omodscan/modbusmessages/modbusmessage.cpp | 94 +++++++++---------- omodscan/modbusmessages/modbusmessage.h | 34 +++++-- omodscan/modbusmessages/readcoils.h | 10 +- omodscan/modbusmessages/readdiscreteinputs.h | 10 +- omodscan/modbusmessages/readexceptionstatus.h | 10 +- omodscan/modbusmessages/readfifoqueue.h | 10 +- omodscan/modbusmessages/readfilerecord.h | 10 +- .../modbusmessages/readholdingregisters.h | 10 +- omodscan/modbusmessages/readinputregisters.h | 10 +- .../readwritemultipleregisters.h | 10 +- omodscan/modbusmessages/reportserverid.h | 10 +- omodscan/modbusmessages/writefilerecord.h | 10 +- omodscan/modbusmessages/writemultiplecoils.h | 10 +- .../modbusmessages/writemultipleregisters.h | 10 +- omodscan/modbusmessages/writesinglecoil.h | 10 +- omodscan/modbusmessages/writesingleregister.h | 10 +- omodscan/qmodbusadu.h | 18 +++- 24 files changed, 230 insertions(+), 142 deletions(-) diff --git a/omodscan/controls/modbusmessagewidget.cpp b/omodscan/controls/modbusmessagewidget.cpp index 90c665a..35d4a61 100644 --- a/omodscan/controls/modbusmessagewidget.cpp +++ b/omodscan/controls/modbusmessagewidget.cpp @@ -125,7 +125,16 @@ void ModbusMessageWidget::update() auto addChecksum = [&]{ if(_msg->protocolType() == QModbusAdu::Rtu) { - addItem(tr("Checksum: %1").arg(formatWordValue(_dataDisplayMode, _msg->checksum()))); + const auto checksum = formatWordValue(_dataDisplayMode, _msg->checksum()); + if(_msg->matchingChecksum()) + { + addItem(tr("Checksum: %1").arg(checksum)); + } + else + { + const auto calcChecksum = formatWordValue(_dataDisplayMode, _msg->calcChecksum()); + addItem(tr("Checksum: %1 (Expected: %2)").arg(checksum, calcChecksum)); + } } }; @@ -134,9 +143,12 @@ void ModbusMessageWidget::update() if(_msg->type() == ModbusMessage::Adu) { - addItem(tr("Transaction ID: %1").arg(formatWordValue(_dataDisplayMode, _msg->transactionId()))); - addItem(tr("Protocol ID: %1").arg(formatWordValue(_dataDisplayMode, _msg->protocolId()))); - addItem(tr("Length: %1").arg(formatWordValue(_dataDisplayMode, _msg->length()))); + const auto transactionId = _msg->isValid() ? formatWordValue(_dataDisplayMode, _msg->transactionId()) : "??"; + const auto protocolId = _msg->isValid() ? formatWordValue(_dataDisplayMode, _msg->protocolId()): "??"; + const auto length = _msg->isValid() ? formatWordValue(_dataDisplayMode, _msg->length()): "??"; + addItem(tr("Transaction ID: %1").arg(transactionId)); + addItem(tr("Protocol ID: %1").arg(protocolId)); + addItem(tr("Length: %1").arg(length)); } addItem(tr("Device ID: %1").arg(formatByteValue(_dataDisplayMode, _msg->deviceId()))); diff --git a/omodscan/dialogs/dialogmsgparser.cpp b/omodscan/dialogs/dialogmsgparser.cpp index 90f7b04..639fa97 100644 --- a/omodscan/dialogs/dialogmsgparser.cpp +++ b/omodscan/dialogs/dialogmsgparser.cpp @@ -65,14 +65,26 @@ void DialogMsgParser::accept() auto data = ui->bytesData->value(); ModbusMessage::Type type = ModbusMessage::Adu; - const auto protocol = ui->checksum->isChecked() ? QModbusAdu::Rtu : QModbusAdu::Tcp; + auto protocol = QModbusAdu::Tcp; + int checksum = 0; if(ui->buttonPdu->isChecked()) { type = ModbusMessage::Pdu; - if(!ui->deviceIdIncluded->isChecked()) data.push_front('\0'); } - _mm = ModbusMessage::parse(data, type, protocol, ui->request->isChecked()); + if(!ui->deviceIdIncluded->isChecked()) + { + data.push_front('\0'); + } + + if(ui->checksumIncluded->isChecked()) + { + protocol = QModbusAdu::Rtu; + checksum = makeWord(data[data.size() - 1], data[data.size() - 2], ByteOrder::LittleEndian); + data = data.left(data.size() - 2); + } + + _mm = ModbusMessage::parse(data, type, protocol, ui->request->isChecked(), checksum); ui->info->setModbusMessage(_mm); } diff --git a/omodscan/dialogs/dialogmsgparser.ui b/omodscan/dialogs/dialogmsgparser.ui index 5ed666f..7838454 100644 --- a/omodscan/dialogs/dialogmsgparser.ui +++ b/omodscan/dialogs/dialogmsgparser.ui @@ -115,7 +115,7 @@ - + Checksum included @@ -146,6 +146,12 @@ 2 + + Qt::NoFocus + + + Qt::NoContextMenu + true diff --git a/omodscan/modbusmessages/diagnostics.h b/omodscan/modbusmessages/diagnostics.h index d993f81..4cc1261 100644 --- a/omodscan/modbusmessages/diagnostics.h +++ b/omodscan/modbusmessages/diagnostics.h @@ -15,9 +15,10 @@ class DiagnosticsRequest : public ModbusMessage /// \param protocol /// \param deviceId /// \param timestamp + /// \param checksum /// - DiagnosticsRequest(const QModbusPdu& pdu, QModbusAdu::Type protocol, int deviceId, const QDateTime& timestamp) - : ModbusMessage(pdu, protocol, deviceId, timestamp, true) + DiagnosticsRequest(const QModbusPdu& pdu, QModbusAdu::Type protocol, int deviceId, const QDateTime& timestamp, int checksum) + : ModbusMessage(pdu, protocol, deviceId, timestamp, true, checksum) { Q_ASSERT(functionCode() == QModbusPdu::Diagnostics); } @@ -71,9 +72,10 @@ class DiagnosticsResponse : public ModbusMessage /// \param protocol /// \param deviceId /// \param timestamp + /// \param checksum /// - DiagnosticsResponse(const QModbusPdu& pdu, QModbusAdu::Type protocol, int deviceId, const QDateTime& timestamp) - :ModbusMessage(pdu, protocol, deviceId, timestamp, false) + DiagnosticsResponse(const QModbusPdu& pdu, QModbusAdu::Type protocol, int deviceId, const QDateTime& timestamp, int checksum) + :ModbusMessage(pdu, protocol, deviceId, timestamp, false, checksum) { Q_ASSERT(functionCode() == QModbusPdu::Diagnostics); } diff --git a/omodscan/modbusmessages/getcommeventcounter.h b/omodscan/modbusmessages/getcommeventcounter.h index 8aa7273..85aec41 100644 --- a/omodscan/modbusmessages/getcommeventcounter.h +++ b/omodscan/modbusmessages/getcommeventcounter.h @@ -15,9 +15,10 @@ class GetCommEventCounterRequest : public ModbusMessage /// \param protocol /// \param deviceId /// \param timestamp + /// \param checksum /// - GetCommEventCounterRequest(const QModbusPdu& pdu, QModbusAdu::Type protocol, int deviceId, const QDateTime& timestamp) - : ModbusMessage(pdu, protocol, deviceId, timestamp, true) + GetCommEventCounterRequest(const QModbusPdu& pdu, QModbusAdu::Type protocol, int deviceId, const QDateTime& timestamp, int checksum) + : ModbusMessage(pdu, protocol, deviceId, timestamp, true, checksum) { Q_ASSERT(functionCode() == QModbusPdu::GetCommEventCounter); } @@ -46,9 +47,10 @@ class GetCommEventCounterResponse : public ModbusMessage /// \param protocol /// \param deviceId /// \param timestamp + /// \param checksum /// - GetCommEventCounterResponse(const QModbusPdu& pdu, QModbusAdu::Type protocol, int deviceId, const QDateTime& timestamp) - :ModbusMessage(pdu, protocol, deviceId, timestamp, false) + GetCommEventCounterResponse(const QModbusPdu& pdu, QModbusAdu::Type protocol, int deviceId, const QDateTime& timestamp, int checksum) + :ModbusMessage(pdu, protocol, deviceId, timestamp, false, checksum) { Q_ASSERT(functionCode() == QModbusPdu::GetCommEventCounter); } diff --git a/omodscan/modbusmessages/getcommeventlog.h b/omodscan/modbusmessages/getcommeventlog.h index b10425f..f22c440 100644 --- a/omodscan/modbusmessages/getcommeventlog.h +++ b/omodscan/modbusmessages/getcommeventlog.h @@ -15,9 +15,10 @@ class GetCommEventLogRequest : public ModbusMessage /// \param protocol /// \param deviceId /// \param timestamp + /// \param checksum /// - GetCommEventLogRequest(const QModbusPdu& pdu, QModbusAdu::Type protocol, int deviceId, const QDateTime& timestamp) - : ModbusMessage(pdu, protocol, deviceId, timestamp, true) + GetCommEventLogRequest(const QModbusPdu& pdu, QModbusAdu::Type protocol, int deviceId, const QDateTime& timestamp, int checksum) + : ModbusMessage(pdu, protocol, deviceId, timestamp, true, checksum) { Q_ASSERT(functionCode() == QModbusPdu::GetCommEventLog); } @@ -46,9 +47,10 @@ class GetCommEventLogResponse : public ModbusMessage /// \param protocol /// \param deviceId /// \param timestamp + /// \param checksum /// - GetCommEventLogResponse(const QModbusPdu& pdu, QModbusAdu::Type protocol, int deviceId, const QDateTime& timestamp) - :ModbusMessage(pdu, protocol, deviceId, timestamp, false) + GetCommEventLogResponse(const QModbusPdu& pdu, QModbusAdu::Type protocol, int deviceId, const QDateTime& timestamp, int checksum) + :ModbusMessage(pdu, protocol, deviceId, timestamp, false, checksum) { Q_ASSERT(functionCode() == QModbusPdu::GetCommEventLog); } diff --git a/omodscan/modbusmessages/maskwriteregister.h b/omodscan/modbusmessages/maskwriteregister.h index 05a11ec..a622bde 100644 --- a/omodscan/modbusmessages/maskwriteregister.h +++ b/omodscan/modbusmessages/maskwriteregister.h @@ -15,9 +15,10 @@ class MaskWriteRegisterRequest : public ModbusMessage /// \param protocol /// \param deviceId /// \param timestamp + /// \param checksum /// - MaskWriteRegisterRequest(const QModbusPdu& pdu, QModbusAdu::Type protocol, int deviceId, const QDateTime& timestamp) - : ModbusMessage(pdu, protocol, deviceId, timestamp, true) + MaskWriteRegisterRequest(const QModbusPdu& pdu, QModbusAdu::Type protocol, int deviceId, const QDateTime& timestamp, int checksum) + : ModbusMessage(pdu, protocol, deviceId, timestamp, true, checksum) { Q_ASSERT(functionCode() == QModbusPdu::MaskWriteRegister); } @@ -78,9 +79,10 @@ class MaskWriteRegisterResponse : public ModbusMessage /// \param protocol /// \param deviceId /// \param timestamp + /// \param checksum /// - MaskWriteRegisterResponse(const QModbusPdu& pdu, QModbusAdu::Type protocol, int deviceId, const QDateTime& timestamp) - :ModbusMessage(pdu, protocol, deviceId, timestamp, false) + MaskWriteRegisterResponse(const QModbusPdu& pdu, QModbusAdu::Type protocol, int deviceId, const QDateTime& timestamp, int checksum) + :ModbusMessage(pdu, protocol, deviceId, timestamp, false, checksum) { Q_ASSERT(functionCode() == QModbusPdu::MaskWriteRegister); } diff --git a/omodscan/modbusmessages/modbusmessage.cpp b/omodscan/modbusmessages/modbusmessage.cpp index 5b1d043..6a5aefc 100644 --- a/omodscan/modbusmessages/modbusmessage.cpp +++ b/omodscan/modbusmessages/modbusmessage.cpp @@ -8,86 +8,87 @@ /// \param deviceId /// \param timestamp /// \param request +/// \param checksum /// \return /// -const ModbusMessage* ModbusMessage::create(const QModbusPdu& pdu, QModbusAdu::Type protocol, int deviceId, const QDateTime& timestamp, bool request) +const ModbusMessage* ModbusMessage::create(const QModbusPdu& pdu, QModbusAdu::Type protocol, int deviceId, const QDateTime& timestamp, bool request, int checksum) { switch(pdu.functionCode()) { case QModbusPdu::ReadCoils: - if(request) return new ReadCoilsRequest(pdu, protocol, deviceId, timestamp); - else return new ReadCoilsResponse(pdu, protocol, deviceId, timestamp); + if(request) return new ReadCoilsRequest(pdu, protocol, deviceId, timestamp, checksum); + else return new ReadCoilsResponse(pdu, protocol, deviceId, timestamp, checksum); case QModbusPdu::ReadDiscreteInputs: - if(request) return new ReadDiscreteInputsRequest(pdu, protocol, deviceId, timestamp); - else return new ReadDiscreteInputsResponse(pdu, protocol, deviceId, timestamp); + if(request) return new ReadDiscreteInputsRequest(pdu, protocol, deviceId, timestamp, checksum); + else return new ReadDiscreteInputsResponse(pdu, protocol, deviceId, timestamp, checksum); case QModbusPdu::ReadHoldingRegisters: - if(request) return new ReadHoldingRegistersRequest(pdu, protocol, deviceId, timestamp); - else return new ReadHoldingRegistersResponse(pdu, protocol, deviceId, timestamp); + if(request) return new ReadHoldingRegistersRequest(pdu, protocol, deviceId, timestamp, checksum); + else return new ReadHoldingRegistersResponse(pdu, protocol, deviceId, timestamp, checksum); case QModbusPdu::ReadInputRegisters: - if(request) return new ReadInputRegistersRequest(pdu, protocol, deviceId, timestamp); - else return new ReadInputRegistersResponse(pdu, protocol, deviceId, timestamp); + if(request) return new ReadInputRegistersRequest(pdu, protocol, deviceId, timestamp, checksum); + else return new ReadInputRegistersResponse(pdu, protocol, deviceId, timestamp, checksum); case QModbusPdu::WriteSingleCoil: - if(request) return new WriteSingleCoilRequest(pdu, protocol, deviceId, timestamp); - else return new WriteSingleCoilResponse(pdu, protocol, deviceId, timestamp); + if(request) return new WriteSingleCoilRequest(pdu, protocol, deviceId, timestamp, checksum); + else return new WriteSingleCoilResponse(pdu, protocol, deviceId, timestamp, checksum); case QModbusPdu::WriteSingleRegister: - if(request) return new WriteSingleRegisterRequest(pdu, protocol, deviceId, timestamp); - else return new WriteSingleRegisterResponse(pdu, protocol, deviceId, timestamp); + if(request) return new WriteSingleRegisterRequest(pdu, protocol, deviceId, timestamp, checksum); + else return new WriteSingleRegisterResponse(pdu, protocol, deviceId, timestamp, checksum); case QModbusPdu::ReadExceptionStatus: - if(request) return new ReadExceptionStatusRequest(pdu, protocol, deviceId, timestamp); - else return new ReadExceptionStatusResponse(pdu, protocol, deviceId, timestamp); + if(request) return new ReadExceptionStatusRequest(pdu, protocol, deviceId, timestamp, checksum); + else return new ReadExceptionStatusResponse(pdu, protocol, deviceId, timestamp, checksum); case QModbusPdu::Diagnostics: - if(request) return new DiagnosticsRequest(pdu, protocol, deviceId, timestamp); - else return new DiagnosticsResponse(pdu, protocol, deviceId, timestamp); + if(request) return new DiagnosticsRequest(pdu, protocol, deviceId, timestamp, checksum); + else return new DiagnosticsResponse(pdu, protocol, deviceId, timestamp, checksum); case QModbusPdu::GetCommEventCounter: - if(request) return new GetCommEventCounterRequest(pdu, protocol, deviceId, timestamp); - else return new GetCommEventCounterResponse(pdu, protocol, deviceId, timestamp); + if(request) return new GetCommEventCounterRequest(pdu, protocol, deviceId, timestamp, checksum); + else return new GetCommEventCounterResponse(pdu, protocol, deviceId, timestamp, checksum); case QModbusPdu::GetCommEventLog: - if(request) return new GetCommEventLogRequest(pdu, protocol, deviceId, timestamp); - else return new GetCommEventLogResponse(pdu, protocol, deviceId, timestamp); + if(request) return new GetCommEventLogRequest(pdu, protocol, deviceId, timestamp, checksum); + else return new GetCommEventLogResponse(pdu, protocol, deviceId, timestamp, checksum); case QModbusPdu::WriteMultipleCoils: - if(request) return new WriteMultipleCoilsRequest(pdu, protocol, deviceId, timestamp); - else return new WriteMultipleCoilsResponse(pdu, protocol, deviceId, timestamp); + if(request) return new WriteMultipleCoilsRequest(pdu, protocol, deviceId, timestamp, checksum); + else return new WriteMultipleCoilsResponse(pdu, protocol, deviceId, timestamp, checksum); case QModbusPdu::WriteMultipleRegisters: - if(request) return new WriteMultipleRegistersRequest(pdu, protocol, deviceId, timestamp); - else return new WriteMultipleRegistersResponse(pdu, protocol, deviceId, timestamp); + if(request) return new WriteMultipleRegistersRequest(pdu, protocol, deviceId, timestamp, checksum); + else return new WriteMultipleRegistersResponse(pdu, protocol, deviceId, timestamp, checksum); case QModbusPdu::ReportServerId: - if(request) return new ReportServerIdRequest(pdu, protocol, deviceId, timestamp); - else return new ReportServerIdResponse(pdu, protocol, deviceId, timestamp); + if(request) return new ReportServerIdRequest(pdu, protocol, deviceId, timestamp, checksum); + else return new ReportServerIdResponse(pdu, protocol, deviceId, timestamp, checksum); case QModbusPdu::ReadFileRecord: - if(request) return new ReadFileRecordRequest(pdu, protocol, deviceId, timestamp); - else return new ReadFileRecordResponse(pdu, protocol, deviceId, timestamp); + if(request) return new ReadFileRecordRequest(pdu, protocol, deviceId, timestamp, checksum); + else return new ReadFileRecordResponse(pdu, protocol, deviceId, timestamp, checksum); case QModbusPdu::WriteFileRecord: - if(request) return new WriteFileRecordRequest(pdu, protocol, deviceId, timestamp); - else return new WriteFileRecordResponse(pdu, protocol, deviceId, timestamp); + if(request) return new WriteFileRecordRequest(pdu, protocol, deviceId, timestamp, checksum); + else return new WriteFileRecordResponse(pdu, protocol, deviceId, timestamp, checksum); case QModbusPdu::MaskWriteRegister: - if(request) return new MaskWriteRegisterRequest(pdu, protocol, deviceId, timestamp); - else return new MaskWriteRegisterResponse(pdu, protocol, deviceId, timestamp); + if(request) return new MaskWriteRegisterRequest(pdu, protocol, deviceId, timestamp, checksum); + else return new MaskWriteRegisterResponse(pdu, protocol, deviceId, timestamp, checksum); case QModbusPdu::ReadWriteMultipleRegisters: - if(request) return new ReadWriteMultipleRegistersRequest(pdu, protocol, deviceId, timestamp); - else return new ReadWriteMultipleRegistersResponse(pdu, protocol, deviceId, timestamp); + if(request) return new ReadWriteMultipleRegistersRequest(pdu, protocol, deviceId, timestamp, checksum); + else return new ReadWriteMultipleRegistersResponse(pdu, protocol, deviceId, timestamp, checksum); case QModbusPdu::ReadFifoQueue: - if(request) return new ReadFifoQueueRequest(pdu, protocol, deviceId, timestamp); - else return new ReadFifoQueueResponse(pdu, protocol, deviceId, timestamp); + if(request) return new ReadFifoQueueRequest(pdu, protocol, deviceId, timestamp, checksum); + else return new ReadFifoQueueResponse(pdu, protocol, deviceId, timestamp, checksum); default: - return new ModbusMessage(pdu, protocol, deviceId, timestamp, request); + return new ModbusMessage(pdu, protocol, deviceId, timestamp, request, checksum); } } @@ -185,9 +186,10 @@ const ModbusMessage* ModbusMessage::create(const QModbusAdu& adu, const QDateTim /// \param type /// \param protocol /// \param request +/// \param checksum /// \return /// -const ModbusMessage* ModbusMessage::parse(const QByteArray& data, Type type, QModbusAdu::Type protocol, bool request) +const ModbusMessage* ModbusMessage::parse(const QByteArray& data, Type type, QModbusAdu::Type protocol, bool request, int checksum) { switch(type) { @@ -201,19 +203,9 @@ const ModbusMessage* ModbusMessage::parse(const QByteArray& data, Type type, QMo { QModbusPdu pdu; pdu.setFunctionCode((QModbusPdu::FunctionCode)data[1]); + pdu.setData(data.mid(2, data.size() - 2)); - switch(protocol) - { - case QModbusAdu::Tcp: - pdu.setData(data.mid(2, data.size() - 2)); - break; - - case QModbusAdu::Rtu: - pdu.setData(data.mid(2, data.size() - 4)); - break; - } - - return create(pdu, protocol, data[0], QDateTime::currentDateTime(), request); + return create(pdu, protocol, data[0], QDateTime::currentDateTime(), request, checksum); } default: diff --git a/omodscan/modbusmessages/modbusmessage.h b/omodscan/modbusmessages/modbusmessage.h index 2e2ce24..75a479b 100644 --- a/omodscan/modbusmessages/modbusmessage.h +++ b/omodscan/modbusmessages/modbusmessage.h @@ -26,8 +26,9 @@ class ModbusMessage /// \param deviceId /// \param timestamp /// \param request + /// \param checksum /// - explicit ModbusMessage(const QModbusPdu& pdu, QModbusAdu::Type protocol, int deviceId, const QDateTime& timestamp, bool request) + explicit ModbusMessage(const QModbusPdu& pdu, QModbusAdu::Type protocol, int deviceId, const QDateTime& timestamp, bool request, int checksum) :_type(Type::Pdu) ,_protocol(protocol) ,_data(pdu.data()) @@ -40,7 +41,8 @@ class ModbusMessage ,_deviceId(deviceId) ,_request(request) ,_isValid(pdu.isValid()) - ,_checksum(calcCRC(pdu, deviceId)) + ,_checksum((protocol == QModbusAdu::Rtu) ? checksum : 0) + ,_calcChecksum((protocol == QModbusAdu::Rtu) ? calcCRC(pdu, deviceId) : 0) { } @@ -64,6 +66,7 @@ class ModbusMessage ,_request(request) ,_isValid(adu.isValid()) ,_checksum(adu.checksum()) + ,_calcChecksum(adu.calcChecksum()) { } @@ -81,7 +84,7 @@ class ModbusMessage /// \param request /// \return /// - static const ModbusMessage* create(const QModbusPdu& pdu, QModbusAdu::Type protocol, int deviceId, const QDateTime& timestamp, bool request); + static const ModbusMessage* create(const QModbusPdu& pdu, QModbusAdu::Type protocol, int deviceId, const QDateTime& timestamp, bool request, int checksum = 0); /// /// \brief create @@ -98,9 +101,10 @@ class ModbusMessage /// \param type /// \param protocol /// \param request + /// \param checksum /// \return /// - static const ModbusMessage* parse(const QByteArray& data, Type type, QModbusAdu::Type protocol, bool request); + static const ModbusMessage* parse(const QByteArray& data, Type type, QModbusAdu::Type protocol, bool request, int checksum = 0); /// /// \brief type @@ -147,7 +151,8 @@ class ModbusMessage /// \return /// virtual bool isValid() const { - return (_deviceId == 0 || ModbusLimits::slaveRange().contains(_deviceId)) && _isValid; + return (_deviceId == 0 || ModbusLimits::slaveRange().contains(_deviceId)) && + matchingChecksum() && _isValid; } /// @@ -232,6 +237,22 @@ class ModbusMessage return _checksum; } + /// + /// \brief calcChecksum + /// \return + /// + int calcChecksum() const { + return _calcChecksum; + } + + /// + /// \brief matchingChecksum + /// \return + /// + bool matchingChecksum() const { + return _calcChecksum == _checksum; + } + /// /// \brief operator QByteArray /// @@ -299,7 +320,7 @@ class ModbusMessage data.push_back(deviceId); data.push_back(pdu.functionCode()); data.push_back(pdu.data()); - qDebug() << formatByteArray(DataDisplayMode::Hex, data); + return QModbusAdu::calculateCRC(data, data.length()); } @@ -317,6 +338,7 @@ class ModbusMessage const bool _request; const bool _isValid; const int _checksum; + const int _calcChecksum; }; Q_DECLARE_METATYPE(const ModbusMessage*) diff --git a/omodscan/modbusmessages/readcoils.h b/omodscan/modbusmessages/readcoils.h index 04e7484..a29703b 100644 --- a/omodscan/modbusmessages/readcoils.h +++ b/omodscan/modbusmessages/readcoils.h @@ -16,9 +16,10 @@ class ReadCoilsRequest : public ModbusMessage /// \param protocol /// \param deviceId /// \param timestamp + /// \param checksum /// - ReadCoilsRequest(const QModbusPdu& pdu, QModbusAdu::Type protocol, int deviceId, const QDateTime& timestamp) - : ModbusMessage(pdu, protocol, deviceId, timestamp, true) + ReadCoilsRequest(const QModbusPdu& pdu, QModbusAdu::Type protocol, int deviceId, const QDateTime& timestamp, int checksum) + : ModbusMessage(pdu, protocol, deviceId, timestamp, true, checksum) { Q_ASSERT(functionCode() == QModbusPdu::ReadCoils); } @@ -72,9 +73,10 @@ class ReadCoilsResponse : public ModbusMessage /// \param protocol /// \param deviceId /// \param timestamp + /// \param checksum /// - ReadCoilsResponse(const QModbusPdu& pdu, QModbusAdu::Type protocol, int deviceId, const QDateTime& timestamp) - :ModbusMessage(pdu, protocol, deviceId, timestamp, false) + ReadCoilsResponse(const QModbusPdu& pdu, QModbusAdu::Type protocol, int deviceId, const QDateTime& timestamp, int checksum) + :ModbusMessage(pdu, protocol, deviceId, timestamp, false, checksum) { Q_ASSERT(functionCode() == QModbusPdu::ReadCoils); } diff --git a/omodscan/modbusmessages/readdiscreteinputs.h b/omodscan/modbusmessages/readdiscreteinputs.h index 0f83bd4..17fa22c 100644 --- a/omodscan/modbusmessages/readdiscreteinputs.h +++ b/omodscan/modbusmessages/readdiscreteinputs.h @@ -15,9 +15,10 @@ class ReadDiscreteInputsRequest : public ModbusMessage /// \param protocol /// \param deviceId /// \param timestamp + /// \param checksum /// - ReadDiscreteInputsRequest(const QModbusPdu& pdu, QModbusAdu::Type protocol, int deviceId, const QDateTime& timestamp) - : ModbusMessage(pdu, protocol, deviceId, timestamp, true) + ReadDiscreteInputsRequest(const QModbusPdu& pdu, QModbusAdu::Type protocol, int deviceId, const QDateTime& timestamp, int checksum) + : ModbusMessage(pdu, protocol, deviceId, timestamp, true, checksum) { Q_ASSERT(functionCode() == QModbusPdu::ReadDiscreteInputs); } @@ -71,9 +72,10 @@ class ReadDiscreteInputsResponse : public ModbusMessage /// \param protocol /// \param deviceId /// \param timestamp + /// \param checksum /// - ReadDiscreteInputsResponse(const QModbusPdu& pdu, QModbusAdu::Type protocol, int deviceId, const QDateTime& timestamp) - :ModbusMessage(pdu, protocol, deviceId, timestamp, false) + ReadDiscreteInputsResponse(const QModbusPdu& pdu, QModbusAdu::Type protocol, int deviceId, const QDateTime& timestamp, int checksum) + :ModbusMessage(pdu, protocol, deviceId, timestamp, false, checksum) { Q_ASSERT(functionCode() == QModbusPdu::ReadDiscreteInputs); } diff --git a/omodscan/modbusmessages/readexceptionstatus.h b/omodscan/modbusmessages/readexceptionstatus.h index 8c73ee0..d127724 100644 --- a/omodscan/modbusmessages/readexceptionstatus.h +++ b/omodscan/modbusmessages/readexceptionstatus.h @@ -15,9 +15,10 @@ class ReadExceptionStatusRequest : public ModbusMessage /// \param protocol /// \param deviceId /// \param timestamp + /// \param checksum /// - ReadExceptionStatusRequest(const QModbusPdu& pdu, QModbusAdu::Type protocol, int deviceId, const QDateTime& timestamp) - : ModbusMessage(pdu, protocol, deviceId, timestamp, true) + ReadExceptionStatusRequest(const QModbusPdu& pdu, QModbusAdu::Type protocol, int deviceId, const QDateTime& timestamp, int checksum) + : ModbusMessage(pdu, protocol, deviceId, timestamp, true, checksum) { Q_ASSERT(functionCode() == QModbusPdu::ReadExceptionStatus); } @@ -46,9 +47,10 @@ class ReadExceptionStatusResponse : public ModbusMessage /// \param protocol /// \param deviceId /// \param timestamp + /// \param checksum /// - ReadExceptionStatusResponse(const QModbusPdu& pdu, QModbusAdu::Type protocol, int deviceId, const QDateTime& timestamp) - :ModbusMessage(pdu, protocol, deviceId, timestamp, false) + ReadExceptionStatusResponse(const QModbusPdu& pdu, QModbusAdu::Type protocol, int deviceId, const QDateTime& timestamp, int checksum) + :ModbusMessage(pdu, protocol, deviceId, timestamp, false, checksum) { Q_ASSERT(functionCode() == QModbusPdu::ReadExceptionStatus); } diff --git a/omodscan/modbusmessages/readfifoqueue.h b/omodscan/modbusmessages/readfifoqueue.h index 73dd838..9be9c1e 100644 --- a/omodscan/modbusmessages/readfifoqueue.h +++ b/omodscan/modbusmessages/readfifoqueue.h @@ -15,9 +15,10 @@ class ReadFifoQueueRequest : public ModbusMessage /// \param protocol /// \param deviceId /// \param timestamp + /// \param checksum /// - ReadFifoQueueRequest(const QModbusPdu& pdu, QModbusAdu::Type protocol, int deviceId, const QDateTime& timestamp) - : ModbusMessage(pdu, protocol, deviceId, timestamp, true) + ReadFifoQueueRequest(const QModbusPdu& pdu, QModbusAdu::Type protocol, int deviceId, const QDateTime& timestamp, int checksum) + : ModbusMessage(pdu, protocol, deviceId, timestamp, true, checksum) { Q_ASSERT(functionCode() == QModbusPdu::ReadFifoQueue); } @@ -62,9 +63,10 @@ class ReadFifoQueueResponse : public ModbusMessage /// \param protocol /// \param deviceId /// \param timestamp + /// \param checksum /// - ReadFifoQueueResponse(const QModbusPdu& pdu, QModbusAdu::Type protocol, int deviceId, const QDateTime& timestamp) - :ModbusMessage(pdu, protocol, deviceId, timestamp, false) + ReadFifoQueueResponse(const QModbusPdu& pdu, QModbusAdu::Type protocol, int deviceId, const QDateTime& timestamp, int checksum) + :ModbusMessage(pdu, protocol, deviceId, timestamp, false, checksum) { Q_ASSERT(functionCode() == QModbusPdu::ReadFifoQueue); } diff --git a/omodscan/modbusmessages/readfilerecord.h b/omodscan/modbusmessages/readfilerecord.h index ce5c916..aabe672 100644 --- a/omodscan/modbusmessages/readfilerecord.h +++ b/omodscan/modbusmessages/readfilerecord.h @@ -15,9 +15,10 @@ class ReadFileRecordRequest : public ModbusMessage /// \param protocol /// \param deviceId /// \param timestamp + /// \param checksum /// - ReadFileRecordRequest(const QModbusPdu& pdu, QModbusAdu::Type protocol, int deviceId, const QDateTime& timestamp) - : ModbusMessage(pdu, protocol, deviceId, timestamp, true) + ReadFileRecordRequest(const QModbusPdu& pdu, QModbusAdu::Type protocol, int deviceId, const QDateTime& timestamp, int checksum) + : ModbusMessage(pdu, protocol, deviceId, timestamp, true, checksum) { Q_ASSERT(functionCode() == QModbusPdu::ReadFileRecord); } @@ -71,9 +72,10 @@ class ReadFileRecordResponse : public ModbusMessage /// \param protocol /// \param deviceId /// \param timestamp + /// \param checksum /// - ReadFileRecordResponse(const QModbusPdu& pdu, QModbusAdu::Type protocol, int deviceId, const QDateTime& timestamp) - :ModbusMessage(pdu, protocol, deviceId, timestamp, false) + ReadFileRecordResponse(const QModbusPdu& pdu, QModbusAdu::Type protocol, int deviceId, const QDateTime& timestamp, int checksum) + :ModbusMessage(pdu, protocol, deviceId, timestamp, false, checksum) { Q_ASSERT(functionCode() == QModbusPdu::ReadFileRecord); } diff --git a/omodscan/modbusmessages/readholdingregisters.h b/omodscan/modbusmessages/readholdingregisters.h index 4a2fe25..3ebdc84 100644 --- a/omodscan/modbusmessages/readholdingregisters.h +++ b/omodscan/modbusmessages/readholdingregisters.h @@ -15,9 +15,10 @@ class ReadHoldingRegistersRequest : public ModbusMessage /// \param protocol /// \param deviceId /// \param timestamp + /// \param checksum /// - ReadHoldingRegistersRequest(const QModbusPdu& pdu, QModbusAdu::Type protocol, int deviceId, const QDateTime& timestamp) - : ModbusMessage(pdu, protocol, deviceId, timestamp, true) + ReadHoldingRegistersRequest(const QModbusPdu& pdu, QModbusAdu::Type protocol, int deviceId, const QDateTime& timestamp, int checksum) + : ModbusMessage(pdu, protocol, deviceId, timestamp, true, checksum) { Q_ASSERT(functionCode() == QModbusPdu::ReadHoldingRegisters); } @@ -71,9 +72,10 @@ class ReadHoldingRegistersResponse : public ModbusMessage /// \param protocol /// \param deviceId /// \param timestamp + /// \param checksum /// - ReadHoldingRegistersResponse(const QModbusPdu& pdu, QModbusAdu::Type protocol, int deviceId, const QDateTime& timestamp) - :ModbusMessage(pdu, protocol, deviceId, timestamp, false) + ReadHoldingRegistersResponse(const QModbusPdu& pdu, QModbusAdu::Type protocol, int deviceId, const QDateTime& timestamp, int checksum) + :ModbusMessage(pdu, protocol, deviceId, timestamp, false, checksum) { Q_ASSERT(functionCode() == QModbusPdu::ReadHoldingRegisters); } diff --git a/omodscan/modbusmessages/readinputregisters.h b/omodscan/modbusmessages/readinputregisters.h index 92a1b55..7b221db 100644 --- a/omodscan/modbusmessages/readinputregisters.h +++ b/omodscan/modbusmessages/readinputregisters.h @@ -15,9 +15,10 @@ class ReadInputRegistersRequest : public ModbusMessage /// \param protocol /// \param deviceId /// \param timestamp + /// \param checksum /// - ReadInputRegistersRequest(const QModbusPdu& pdu, QModbusAdu::Type protocol, int deviceId, const QDateTime& timestamp) - : ModbusMessage(pdu, protocol, deviceId, timestamp, true) + ReadInputRegistersRequest(const QModbusPdu& pdu, QModbusAdu::Type protocol, int deviceId, const QDateTime& timestamp, int checksum) + : ModbusMessage(pdu, protocol, deviceId, timestamp, true, checksum) { Q_ASSERT(functionCode() == QModbusPdu::ReadInputRegisters); } @@ -71,9 +72,10 @@ class ReadInputRegistersResponse : public ModbusMessage /// \param protocol /// \param deviceId /// \param timestamp + /// \param checksum /// - ReadInputRegistersResponse(const QModbusPdu& pdu, QModbusAdu::Type protocol, int deviceId, const QDateTime& timestamp) - :ModbusMessage(pdu, protocol, deviceId, timestamp, false) + ReadInputRegistersResponse(const QModbusPdu& pdu, QModbusAdu::Type protocol, int deviceId, const QDateTime& timestamp, int checksum) + :ModbusMessage(pdu, protocol, deviceId, timestamp, false, checksum) { Q_ASSERT(functionCode() == QModbusPdu::ReadInputRegisters); } diff --git a/omodscan/modbusmessages/readwritemultipleregisters.h b/omodscan/modbusmessages/readwritemultipleregisters.h index d32d274..93b82ac 100644 --- a/omodscan/modbusmessages/readwritemultipleregisters.h +++ b/omodscan/modbusmessages/readwritemultipleregisters.h @@ -15,9 +15,10 @@ class ReadWriteMultipleRegistersRequest : public ModbusMessage /// \param protocol /// \param deviceId /// \param timestamp + /// \param checksum /// - ReadWriteMultipleRegistersRequest(const QModbusPdu& pdu, QModbusAdu::Type protocol, int deviceId, const QDateTime& timestamp) - : ModbusMessage(pdu, protocol, deviceId, timestamp, true) + ReadWriteMultipleRegistersRequest(const QModbusPdu& pdu, QModbusAdu::Type protocol, int deviceId, const QDateTime& timestamp, int checksum) + : ModbusMessage(pdu, protocol, deviceId, timestamp, true, checksum) { Q_ASSERT(functionCode() == QModbusPdu::ReadWriteMultipleRegisters); } @@ -106,9 +107,10 @@ class ReadWriteMultipleRegistersResponse : public ModbusMessage /// \param protocol /// \param deviceId /// \param timestamp + /// \param checksum /// - ReadWriteMultipleRegistersResponse(const QModbusPdu& pdu, QModbusAdu::Type protocol, int deviceId, const QDateTime& timestamp) - :ModbusMessage(pdu, protocol, deviceId, timestamp, false) + ReadWriteMultipleRegistersResponse(const QModbusPdu& pdu, QModbusAdu::Type protocol, int deviceId, const QDateTime& timestamp, int checksum) + :ModbusMessage(pdu, protocol, deviceId, timestamp, false, checksum) { Q_ASSERT(functionCode() == QModbusPdu::ReadWriteMultipleRegisters); } diff --git a/omodscan/modbusmessages/reportserverid.h b/omodscan/modbusmessages/reportserverid.h index 17b6b1e..0098fc0 100644 --- a/omodscan/modbusmessages/reportserverid.h +++ b/omodscan/modbusmessages/reportserverid.h @@ -15,9 +15,10 @@ class ReportServerIdRequest : public ModbusMessage /// \param protocol /// \param deviceId /// \param timestamp + /// \param checksum /// - ReportServerIdRequest(const QModbusPdu& pdu, QModbusAdu::Type protocol, int deviceId, const QDateTime& timestamp) - : ModbusMessage(pdu, protocol, deviceId, timestamp, true) + ReportServerIdRequest(const QModbusPdu& pdu, QModbusAdu::Type protocol, int deviceId, const QDateTime& timestamp, int checksum) + : ModbusMessage(pdu, protocol, deviceId, timestamp, true, checksum) { Q_ASSERT(functionCode() == QModbusPdu::ReportServerId); } @@ -46,9 +47,10 @@ class ReportServerIdResponse : public ModbusMessage /// \param protocol /// \param deviceId /// \param timestamp + /// \param checksum /// - ReportServerIdResponse(const QModbusPdu& pdu, QModbusAdu::Type protocol, int deviceId, const QDateTime& timestamp) - :ModbusMessage(pdu, protocol, deviceId, timestamp, false) + ReportServerIdResponse(const QModbusPdu& pdu, QModbusAdu::Type protocol, int deviceId, const QDateTime& timestamp, int checksum) + :ModbusMessage(pdu, protocol, deviceId, timestamp, false, checksum) { Q_ASSERT(functionCode() == QModbusPdu::ReportServerId); } diff --git a/omodscan/modbusmessages/writefilerecord.h b/omodscan/modbusmessages/writefilerecord.h index 3be7ceb..807f260 100644 --- a/omodscan/modbusmessages/writefilerecord.h +++ b/omodscan/modbusmessages/writefilerecord.h @@ -15,9 +15,10 @@ class WriteFileRecordRequest : public ModbusMessage /// \param protocol /// \param deviceId /// \param timestamp + /// \param checksum /// - WriteFileRecordRequest(const QModbusPdu& pdu, QModbusAdu::Type protocol, int deviceId, const QDateTime& timestamp) - : ModbusMessage(pdu, protocol, deviceId, timestamp, true) + WriteFileRecordRequest(const QModbusPdu& pdu, QModbusAdu::Type protocol, int deviceId, const QDateTime& timestamp, int checksum) + : ModbusMessage(pdu, protocol, deviceId, timestamp, true, checksum) { Q_ASSERT(functionCode() == QModbusPdu::WriteFileRecord); } @@ -72,9 +73,10 @@ class WriteFileRecordResponse : public ModbusMessage /// \param protocol /// \param deviceId /// \param timestamp + /// \param checksum /// - WriteFileRecordResponse(const QModbusPdu& pdu, QModbusAdu::Type protocol, int deviceId, const QDateTime& timestamp) - :ModbusMessage(pdu, protocol, deviceId, timestamp, false) + WriteFileRecordResponse(const QModbusPdu& pdu, QModbusAdu::Type protocol, int deviceId, const QDateTime& timestamp, int checksum) + :ModbusMessage(pdu, protocol, deviceId, timestamp, false, checksum) { Q_ASSERT(functionCode() == QModbusPdu::WriteFileRecord); } diff --git a/omodscan/modbusmessages/writemultiplecoils.h b/omodscan/modbusmessages/writemultiplecoils.h index 8e36b4d..07e776f 100644 --- a/omodscan/modbusmessages/writemultiplecoils.h +++ b/omodscan/modbusmessages/writemultiplecoils.h @@ -15,9 +15,10 @@ class WriteMultipleCoilsRequest : public ModbusMessage /// \param protocol /// \param deviceId /// \param timestamp + /// \param checksum /// - WriteMultipleCoilsRequest(const QModbusPdu& pdu, QModbusAdu::Type protocol, int deviceId, const QDateTime& timestamp) - : ModbusMessage(pdu, protocol, deviceId, timestamp, true) + WriteMultipleCoilsRequest(const QModbusPdu& pdu, QModbusAdu::Type protocol, int deviceId, const QDateTime& timestamp, int checksum) + : ModbusMessage(pdu, protocol, deviceId, timestamp, true, checksum) { Q_ASSERT(functionCode() == QModbusPdu::WriteMultipleCoils); } @@ -88,9 +89,10 @@ class WriteMultipleCoilsResponse : public ModbusMessage /// \param protocol /// \param deviceId /// \param timestamp + /// \param checksum /// - WriteMultipleCoilsResponse(const QModbusPdu& pdu, QModbusAdu::Type protocol, int deviceId, const QDateTime& timestamp) - :ModbusMessage(pdu, protocol, deviceId, timestamp, false) + WriteMultipleCoilsResponse(const QModbusPdu& pdu, QModbusAdu::Type protocol, int deviceId, const QDateTime& timestamp, int checksum) + :ModbusMessage(pdu, protocol, deviceId, timestamp, false, checksum) { Q_ASSERT(functionCode() == QModbusPdu::WriteMultipleCoils); } diff --git a/omodscan/modbusmessages/writemultipleregisters.h b/omodscan/modbusmessages/writemultipleregisters.h index 90d0d91..925733f 100644 --- a/omodscan/modbusmessages/writemultipleregisters.h +++ b/omodscan/modbusmessages/writemultipleregisters.h @@ -15,9 +15,10 @@ class WriteMultipleRegistersRequest : public ModbusMessage /// \param protocol /// \param deviceId /// \param timestamp + /// \param checksum /// - WriteMultipleRegistersRequest(const QModbusPdu& pdu, QModbusAdu::Type protocol, int deviceId, const QDateTime& timestamp) - : ModbusMessage(pdu, protocol, deviceId, timestamp, true) + WriteMultipleRegistersRequest(const QModbusPdu& pdu, QModbusAdu::Type protocol, int deviceId, const QDateTime& timestamp, int checksum) + : ModbusMessage(pdu, protocol, deviceId, timestamp, true, checksum) { Q_ASSERT(functionCode() == QModbusPdu::WriteMultipleRegisters); } @@ -88,9 +89,10 @@ class WriteMultipleRegistersResponse : public ModbusMessage /// \param protocol /// \param deviceId /// \param timestamp + /// \param checksum /// - WriteMultipleRegistersResponse(const QModbusPdu& pdu, QModbusAdu::Type protocol, int deviceId, const QDateTime& timestamp) - :ModbusMessage(pdu, protocol, deviceId, timestamp, false) + WriteMultipleRegistersResponse(const QModbusPdu& pdu, QModbusAdu::Type protocol, int deviceId, const QDateTime& timestamp, int checksum) + :ModbusMessage(pdu, protocol, deviceId, timestamp, false, checksum) { Q_ASSERT(functionCode() == QModbusPdu::WriteMultipleRegisters); } diff --git a/omodscan/modbusmessages/writesinglecoil.h b/omodscan/modbusmessages/writesinglecoil.h index 4dae125..d02b810 100644 --- a/omodscan/modbusmessages/writesinglecoil.h +++ b/omodscan/modbusmessages/writesinglecoil.h @@ -15,9 +15,10 @@ class WriteSingleCoilRequest : public ModbusMessage /// \param protocol /// \param deviceId /// \param timestamp + /// \param checksum /// - WriteSingleCoilRequest(const QModbusPdu& pdu, QModbusAdu::Type protocol, int deviceId, const QDateTime& timestamp) - : ModbusMessage(pdu, protocol, deviceId, timestamp, true) + WriteSingleCoilRequest(const QModbusPdu& pdu, QModbusAdu::Type protocol, int deviceId, const QDateTime& timestamp, int checksum) + : ModbusMessage(pdu, protocol, deviceId, timestamp, true, checksum) { Q_ASSERT(functionCode() == QModbusPdu::WriteSingleCoil); } @@ -71,9 +72,10 @@ class WriteSingleCoilResponse : public ModbusMessage /// \param protocol /// \param deviceId /// \param timestamp + /// \param checksum /// - WriteSingleCoilResponse(const QModbusPdu& pdu, QModbusAdu::Type protocol, int deviceId, const QDateTime& timestamp) - :ModbusMessage(pdu, protocol, deviceId, timestamp, false) + WriteSingleCoilResponse(const QModbusPdu& pdu, QModbusAdu::Type protocol, int deviceId, const QDateTime& timestamp, int checksum) + :ModbusMessage(pdu, protocol, deviceId, timestamp, false, checksum) { Q_ASSERT(functionCode() == QModbusPdu::WriteSingleCoil); } diff --git a/omodscan/modbusmessages/writesingleregister.h b/omodscan/modbusmessages/writesingleregister.h index 9121dc7..a24ff74 100644 --- a/omodscan/modbusmessages/writesingleregister.h +++ b/omodscan/modbusmessages/writesingleregister.h @@ -15,9 +15,10 @@ class WriteSingleRegisterRequest : public ModbusMessage /// \param protocol /// \param deviceId /// \param timestamp + /// \param checksum /// - WriteSingleRegisterRequest(const QModbusPdu& pdu, QModbusAdu::Type protocol, int deviceId, const QDateTime& timestamp) - : ModbusMessage(pdu, protocol, deviceId, timestamp, true) + WriteSingleRegisterRequest(const QModbusPdu& pdu, QModbusAdu::Type protocol, int deviceId, const QDateTime& timestamp, int checksum) + : ModbusMessage(pdu, protocol, deviceId, timestamp, true, checksum) { Q_ASSERT(functionCode() == QModbusPdu::WriteSingleRegister); } @@ -70,9 +71,10 @@ class WriteSingleRegisterResponse : public ModbusMessage /// \param protocol /// \param deviceId /// \param timestamp + /// \param checksum /// - WriteSingleRegisterResponse(const QModbusPdu& pdu, QModbusAdu::Type protocol, int deviceId, const QDateTime& timestamp) - :ModbusMessage(pdu, protocol, deviceId, timestamp, false) + WriteSingleRegisterResponse(const QModbusPdu& pdu, QModbusAdu::Type protocol, int deviceId, const QDateTime& timestamp, int checksum) + :ModbusMessage(pdu, protocol, deviceId, timestamp, false, checksum) { Q_ASSERT(functionCode() == QModbusPdu::WriteSingleRegister); } diff --git a/omodscan/qmodbusadu.h b/omodscan/qmodbusadu.h index 6583607..38ccbb8 100644 --- a/omodscan/qmodbusadu.h +++ b/omodscan/qmodbusadu.h @@ -37,7 +37,7 @@ class QModbusAdu /// \return /// bool isValid() const { - return _data.size() > 6 && matchingChecksum() && _pdu.isValid(); + return matchingChecksum() && _pdu.isValid() && length() == _pdu.size(); } /// @@ -127,17 +127,25 @@ class QModbusAdu } /// - /// \brief matchingChecksum + /// \brief calcChecksum /// \return /// - bool matchingChecksum() const { + quint16 calcChecksum() const { if(_type == Rtu) { const auto size = _data.size() - 2; // two bytes, CRC const auto data = _data.left(size); - return QModbusAdu::calculateCRC(data, size) == checksum(); + return QModbusAdu::calculateCRC(data, size); } - return true; + return 0; + } + + /// + /// \brief matchingChecksum + /// \return + /// + bool matchingChecksum() const { + return checksum() == calcChecksum(); } inline static quint16 calculateCRC(const char* data, qint32 len){ From 9b7c8870fb94a001a566135bea77603a720db928 Mon Sep 17 00:00:00 2001 From: sanny32 Date: Tue, 10 Oct 2023 16:42:24 +0300 Subject: [PATCH 70/90] Correct formating word array --- omodscan/formatutils.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/omodscan/formatutils.h b/omodscan/formatutils.h index 739be6d..c9d964a 100644 --- a/omodscan/formatutils.h +++ b/omodscan/formatutils.h @@ -75,7 +75,7 @@ inline QString formatWordArray(DataDisplayMode mode, const QByteArray& ar, ByteO break; default: - values += QString("%1").arg(QString::number(value, 16).toUpper(), 4, '0'); + values += QString("0x%1").arg(QString::number(value, 16).toUpper(), 4, '0'); break; } } From 488bbaf487fa2c528ccd106c4361645ee9b87f45 Mon Sep 17 00:00:00 2001 From: sanny32 Date: Tue, 10 Oct 2023 16:53:01 +0300 Subject: [PATCH 71/90] Refactoring --- omodscan/controls/modbusmessagewidget.cpp | 150 +++++++++++----------- omodscan/controls/modbusmessagewidget.h | 2 +- omodscan/dialogs/dialogmsgparser.cpp | 6 +- omodscan/dialogs/dialogmsgparser.ui | 6 - 4 files changed, 79 insertions(+), 85 deletions(-) diff --git a/omodscan/controls/modbusmessagewidget.cpp b/omodscan/controls/modbusmessagewidget.cpp index 35d4a61..da2142d 100644 --- a/omodscan/controls/modbusmessagewidget.cpp +++ b/omodscan/controls/modbusmessagewidget.cpp @@ -12,7 +12,7 @@ ModbusMessageWidget::ModbusMessageWidget(QWidget *parent) ,_byteOrder(ByteOrder::LittleEndian) ,_dataDisplayMode(DataDisplayMode::Decimal) ,_showTimestamp(true) - ,_msg(nullptr) + ,_mm(nullptr) { setItemDelegate(new HtmlDelegate(this)); @@ -24,7 +24,7 @@ ModbusMessageWidget::ModbusMessageWidget(QWidget *parent) /// void ModbusMessageWidget::clear() { - _msg = nullptr; + _mm = nullptr; update(); } @@ -91,7 +91,7 @@ void ModbusMessageWidget::setShowTimestamp(bool on) /// const ModbusMessage* ModbusMessageWidget::modbusMessage() const { - return _msg; + return _mm; } /// @@ -100,7 +100,7 @@ const ModbusMessage* ModbusMessageWidget::modbusMessage() const /// void ModbusMessageWidget::setModbusMessage(const ModbusMessage* msg) { - _msg = msg; + _mm = msg; update(); } @@ -111,69 +111,69 @@ void ModbusMessageWidget::update() { QListWidget::clear(); - if(_msg == nullptr) + if(_mm == nullptr) return; - if(!_msg->isValid()) + if(!_mm->isValid()) { - if(_msg->isRequest()) + if(_mm->isRequest()) addItem(tr("*** INVALID MODBUS REQUEST ***")); - else if(!_msg->isException()) + else if(!_mm->isException()) addItem(tr("*** INVALID MODBUS RESPONSE ***")); } auto addChecksum = [&]{ - if(_msg->protocolType() == QModbusAdu::Rtu) + if(_mm->protocolType() == QModbusAdu::Rtu) { - const auto checksum = formatWordValue(_dataDisplayMode, _msg->checksum()); - if(_msg->matchingChecksum()) + const auto checksum = formatWordValue(_dataDisplayMode, _mm->checksum()); + if(_mm->matchingChecksum()) { addItem(tr("Checksum: %1").arg(checksum)); } else { - const auto calcChecksum = formatWordValue(_dataDisplayMode, _msg->calcChecksum()); + const auto calcChecksum = formatWordValue(_dataDisplayMode, _mm->calcChecksum()); addItem(tr("Checksum: %1 (Expected: %2)").arg(checksum, calcChecksum)); } } }; - addItem(tr("Type: %1").arg(_msg->isRequest() ? tr("Tx Message") : tr("Rx Message"))); - if(_showTimestamp) addItem(tr("Timestamp: %1").arg(_msg->timestamp().toString(Qt::ISODateWithMs))); + addItem(tr("Type: %1").arg(_mm->isRequest() ? tr("Tx Message") : tr("Rx Message"))); + if(_showTimestamp) addItem(tr("Timestamp: %1").arg(_mm->timestamp().toString(Qt::ISODateWithMs))); - if(_msg->type() == ModbusMessage::Adu) + if(_mm->type() == ModbusMessage::Adu) { - const auto transactionId = _msg->isValid() ? formatWordValue(_dataDisplayMode, _msg->transactionId()) : "??"; - const auto protocolId = _msg->isValid() ? formatWordValue(_dataDisplayMode, _msg->protocolId()): "??"; - const auto length = _msg->isValid() ? formatWordValue(_dataDisplayMode, _msg->length()): "??"; + const auto transactionId = _mm->isValid() ? formatWordValue(_dataDisplayMode, _mm->transactionId()) : "??"; + const auto protocolId = _mm->isValid() ? formatWordValue(_dataDisplayMode, _mm->protocolId()): "??"; + const auto length = _mm->isValid() ? formatWordValue(_dataDisplayMode, _mm->length()): "??"; addItem(tr("Transaction ID: %1").arg(transactionId)); addItem(tr("Protocol ID: %1").arg(protocolId)); addItem(tr("Length: %1").arg(length)); } - addItem(tr("Device ID: %1").arg(formatByteValue(_dataDisplayMode, _msg->deviceId()))); + addItem(tr("Device ID: %1").arg(formatByteValue(_dataDisplayMode, _mm->deviceId()))); - if(_msg->isException()) + if(_mm->isException()) { - const auto exception = QString("%1 (%2)").arg(formatByteValue(_dataDisplayMode, _msg->exception()), _msg->exception()); - addItem(tr("Error Code: %1").arg(formatByteValue(_dataDisplayMode, _msg->function()))); + const auto exception = QString("%1 (%2)").arg(formatByteValue(_dataDisplayMode, _mm->exception()), _mm->exception()); + addItem(tr("Error Code: %1").arg(formatByteValue(_dataDisplayMode, _mm->function()))); addItem(tr("Exception Code: %1").arg(exception)); addChecksum(); return; } - const auto func = _msg->function(); + const auto func = _mm->function(); const auto function = func.isValid() ? QString("%1 (%2)").arg(formatByteValue(_dataDisplayMode, func), func) : formatByteValue(_dataDisplayMode, func); addItem(tr("Function Code: %1").arg(function)); - switch(_msg->function()) + switch(_mm->function()) { case QModbusPdu::ReadCoils: - if(_msg->isRequest()) + if(_mm->isRequest()) { - auto req = reinterpret_cast(_msg); + auto req = reinterpret_cast(_mm); const auto startAddress = req->isValid() ? formatWordValue(_dataDisplayMode, req->startAddress()) : "??"; const auto length = req->isValid() ? formatWordValue(_dataDisplayMode, req->length()): "??"; addItem(tr("Start Address: %1").arg(startAddress)); @@ -181,7 +181,7 @@ void ModbusMessageWidget::update() } else { - auto resp = reinterpret_cast(_msg); + auto resp = reinterpret_cast(_mm); const auto byteCount = resp->isValid() ? formatByteValue(_dataDisplayMode, resp->byteCount()) : "?"; const auto coilStatus = resp->isValid() ? formatByteArray(_dataDisplayMode, resp->coilStatus()) : "???"; addItem(tr("Byte Count: %1").arg(byteCount)); @@ -190,9 +190,9 @@ void ModbusMessageWidget::update() break; case QModbusPdu::ReadDiscreteInputs: - if(_msg->isRequest()) + if(_mm->isRequest()) { - auto req = reinterpret_cast(_msg); + auto req = reinterpret_cast(_mm); const auto startAddress = req->isValid() ? formatWordValue(_dataDisplayMode, req->startAddress()) : "??"; const auto length = req->isValid() ? formatWordValue(_dataDisplayMode, req->length()): "??"; addItem(tr("Start Address: %1").arg(startAddress)); @@ -200,7 +200,7 @@ void ModbusMessageWidget::update() } else { - auto resp = reinterpret_cast(_msg); + auto resp = reinterpret_cast(_mm); const auto byteCount = resp->isValid() ? formatByteValue(_dataDisplayMode, resp->byteCount()) : "?"; const auto inputStatus = resp->isValid() ? formatByteArray(_dataDisplayMode, resp->inputStatus()) : "???"; addItem(tr("Byte Count: %1").arg(byteCount)); @@ -209,9 +209,9 @@ void ModbusMessageWidget::update() break; case QModbusPdu::ReadHoldingRegisters: - if(_msg->isRequest()) + if(_mm->isRequest()) { - auto req = reinterpret_cast(_msg); + auto req = reinterpret_cast(_mm); const auto startAddress = req->isValid() ? formatWordValue(_dataDisplayMode, req->startAddress()) : "??"; const auto length = req->isValid() ? formatWordValue(_dataDisplayMode, req->length()): "??"; addItem(tr("Start Address: %1").arg(startAddress)); @@ -219,7 +219,7 @@ void ModbusMessageWidget::update() } else { - auto resp = reinterpret_cast(_msg); + auto resp = reinterpret_cast(_mm); const auto byteCount = resp->isValid() ? formatByteValue(_dataDisplayMode, resp->byteCount()) : "?"; const auto registerValue = resp->isValid() ? formatWordArray(_dataDisplayMode, resp->registerValue(), _byteOrder) : "???"; addItem(tr("Byte Count: %1").arg(byteCount)); @@ -228,9 +228,9 @@ void ModbusMessageWidget::update() break; case QModbusPdu::ReadInputRegisters: - if(_msg->isRequest()) + if(_mm->isRequest()) { - auto req = reinterpret_cast(_msg); + auto req = reinterpret_cast(_mm); const auto startAddress = req->isValid() ? formatWordValue(_dataDisplayMode, req->startAddress()) : "??"; const auto length = req->isValid() ? formatWordValue(_dataDisplayMode, req->length()): "??"; addItem(tr("Start Address: %1").arg(startAddress)); @@ -238,7 +238,7 @@ void ModbusMessageWidget::update() } else { - auto resp = reinterpret_cast(_msg); + auto resp = reinterpret_cast(_mm); const auto byteCount = resp->isValid() ? formatByteValue(_dataDisplayMode, resp->byteCount()) : "?"; const auto registerValue = resp->isValid() ? formatWordArray(_dataDisplayMode, resp->registerValue(), _byteOrder) : "???"; addItem(tr("Byte Count: %1").arg(byteCount)); @@ -247,9 +247,9 @@ void ModbusMessageWidget::update() break; case QModbusPdu::WriteSingleCoil: - if(_msg->isRequest()) + if(_mm->isRequest()) { - auto req = reinterpret_cast(_msg); + auto req = reinterpret_cast(_mm); const auto outputAddress = req->isValid() ? formatWordValue(_dataDisplayMode, req->address()) : "??"; const auto outputValue = req->isValid() ? formatWordValue(_dataDisplayMode, req->value()) : "??"; addItem(tr("Output Address: %1").arg(outputAddress)); @@ -257,7 +257,7 @@ void ModbusMessageWidget::update() } else { - auto resp = reinterpret_cast(_msg); + auto resp = reinterpret_cast(_mm); const auto outputAddress = resp->isValid() ? formatWordValue(_dataDisplayMode, resp->address()) : "??"; const auto outputValue = resp->isValid() ? formatWordValue(_dataDisplayMode, resp->value()) : "??"; addItem(tr("Output Address: %1").arg(outputAddress)); @@ -266,9 +266,9 @@ void ModbusMessageWidget::update() break; case QModbusPdu::WriteSingleRegister: - if(_msg->isRequest()) + if(_mm->isRequest()) { - auto req = reinterpret_cast(_msg); + auto req = reinterpret_cast(_mm); const auto registerAddress = req->isValid() ? formatWordValue(_dataDisplayMode, req->address()) : "??"; const auto registerValue = req->isValid() ? formatWordValue(_dataDisplayMode, req->value()) : "??"; addItem(tr("Register Address: %1").arg(registerAddress)); @@ -276,7 +276,7 @@ void ModbusMessageWidget::update() } else { - auto resp = reinterpret_cast(_msg); + auto resp = reinterpret_cast(_mm); const auto registerAddress = resp->isValid() ? formatWordValue(_dataDisplayMode, resp->address()) : "??"; const auto registerValue = resp->isValid() ? formatWordValue(_dataDisplayMode, resp->value()) : "??"; addItem(tr("Register Address: %1").arg(registerAddress)); @@ -285,18 +285,18 @@ void ModbusMessageWidget::update() break; case QModbusPdu::ReadExceptionStatus: - if(!_msg->isRequest()) + if(!_mm->isRequest()) { - auto resp = reinterpret_cast(_msg); + auto resp = reinterpret_cast(_mm); const auto outputData = resp->isValid() ? formatByteValue(_dataDisplayMode, resp->outputData()) : "?"; addItem(tr("Output Data: %1").arg(outputData)); } break; case QModbusPdu::Diagnostics: - if(_msg->isRequest()) + if(_mm->isRequest()) { - auto req = reinterpret_cast(_msg); + auto req = reinterpret_cast(_mm); const auto subFunc = req->isValid() ? formatWordValue(_dataDisplayMode, req->subfunc()) : "??"; const auto data = req->isValid() ? formatByteArray(_dataDisplayMode, req->data()) : "???"; addItem(tr("Sub-function: %1").arg(subFunc)); @@ -304,7 +304,7 @@ void ModbusMessageWidget::update() } else { - auto resp = reinterpret_cast(_msg); + auto resp = reinterpret_cast(_mm); const auto subFunc = resp->isValid() ? formatWordValue(_dataDisplayMode, resp->subfunc()) : "??"; const auto data = resp->isValid() ? formatByteArray(_dataDisplayMode, resp->data()) : "???"; addItem(tr("Sub-function: %1").arg(subFunc)); @@ -313,9 +313,9 @@ void ModbusMessageWidget::update() break; case QModbusPdu::GetCommEventCounter: - if(!_msg->isRequest()) + if(!_mm->isRequest()) { - auto resp = reinterpret_cast(_msg); + auto resp = reinterpret_cast(_mm); const auto status = resp->isValid() ? formatWordValue(_dataDisplayMode, resp->status()) : "??"; const auto eventCount = resp->isValid() ? formatWordValue(_dataDisplayMode, resp->eventCount()) : "??"; addItem(tr("Status: %1").arg(status)); @@ -324,9 +324,9 @@ void ModbusMessageWidget::update() break; case QModbusPdu::GetCommEventLog: - if(!_msg->isRequest()) + if(!_mm->isRequest()) { - auto resp = reinterpret_cast(_msg); + auto resp = reinterpret_cast(_mm); const auto byteCount = resp->isValid() ? formatByteValue(_dataDisplayMode, resp->byteCount()) : "?"; const auto status = resp->isValid() ? formatWordValue(_dataDisplayMode, resp->status()) : "??"; const auto eventCount = resp->isValid() ? formatWordValue(_dataDisplayMode, resp->eventCount()) : "??"; @@ -341,9 +341,9 @@ void ModbusMessageWidget::update() break; case QModbusPdu::WriteMultipleCoils: - if(_msg->isRequest()) + if(_mm->isRequest()) { - auto req = reinterpret_cast(_msg); + auto req = reinterpret_cast(_mm); const auto startAddr = req->isValid() ? formatWordValue(_dataDisplayMode, req->startAddress()) : "??"; const auto quantity = req->isValid() ? formatWordValue(_dataDisplayMode, req->quantity()) : "??"; const auto byteCount = req->isValid() ? formatByteValue(_dataDisplayMode, req->byteCount()) : "?"; @@ -355,7 +355,7 @@ void ModbusMessageWidget::update() } else { - auto resp = reinterpret_cast(_msg); + auto resp = reinterpret_cast(_mm); const auto startAddr = resp->isValid() ? formatWordValue(_dataDisplayMode, resp->startAddress()) : "??"; const auto quantity = resp->isValid() ? formatWordValue(_dataDisplayMode, resp->quantity()) : "??"; addItem(tr("Starting Address: %1").arg(startAddr)); @@ -364,9 +364,9 @@ void ModbusMessageWidget::update() break; case QModbusPdu::WriteMultipleRegisters: - if(_msg->isRequest()) + if(_mm->isRequest()) { - auto req = reinterpret_cast(_msg); + auto req = reinterpret_cast(_mm); const auto startAddr = req->isValid() ? formatWordValue(_dataDisplayMode, req->startAddress()) : "??"; const auto quantity = req->isValid() ? formatWordValue(_dataDisplayMode, req->quantity()) : "??"; const auto byteCount = req->isValid() ? formatByteValue(_dataDisplayMode, req->byteCount()) : "?"; @@ -378,7 +378,7 @@ void ModbusMessageWidget::update() } else { - auto resp = reinterpret_cast(_msg); + auto resp = reinterpret_cast(_mm); const auto startAddr = resp->isValid() ? formatWordValue(_dataDisplayMode, resp->startAddress()) : "??"; const auto quantity = resp->isValid() ? formatWordValue(_dataDisplayMode, resp->quantity()) : "??"; addItem(tr("Starting Address: %1").arg(startAddr)); @@ -387,9 +387,9 @@ void ModbusMessageWidget::update() break; case QModbusPdu::ReportServerId: - if(!_msg->isRequest()) + if(!_mm->isRequest()) { - auto resp = reinterpret_cast(_msg); + auto resp = reinterpret_cast(_mm); const auto byteCount = resp->isValid() ? formatByteValue(_dataDisplayMode, resp->byteCount()) : "?"; const auto data = resp->isValid() ? formatByteArray(_dataDisplayMode, resp->data()) : "?"; addItem(tr("Byte Count: %1").arg(byteCount)); @@ -398,9 +398,9 @@ void ModbusMessageWidget::update() break; case QModbusPdu::ReadFileRecord: - if(_msg->isRequest()) + if(_mm->isRequest()) { - auto req = reinterpret_cast(_msg); + auto req = reinterpret_cast(_mm); const auto byteCount = req->isValid() ? formatByteValue(_dataDisplayMode, req->byteCount()) : "?"; const auto data = req->isValid() ? formatByteArray(_dataDisplayMode, req->data()) : "?"; addItem(tr("Byte Count: %1").arg(byteCount)); @@ -408,7 +408,7 @@ void ModbusMessageWidget::update() } else { - auto resp = reinterpret_cast(_msg); + auto resp = reinterpret_cast(_mm); const auto byteCount = resp->isValid() ? formatByteValue(_dataDisplayMode, resp->byteCount()) : "?"; const auto data = resp->isValid() ? formatByteArray(_dataDisplayMode, resp->data()) : "?"; addItem(tr("Byte Count: %1").arg(byteCount)); @@ -417,9 +417,9 @@ void ModbusMessageWidget::update() break; case QModbusPdu::WriteFileRecord: - if(_msg->isRequest()) + if(_mm->isRequest()) { - auto req = reinterpret_cast(_msg); + auto req = reinterpret_cast(_mm); const auto length = req->isValid() ? formatByteValue(_dataDisplayMode, req->length()) : "?"; const auto data = req->isValid() ? formatByteArray(_dataDisplayMode, req->data()) : "???"; addItem(tr("Request Data Length: %1").arg(length)); @@ -427,7 +427,7 @@ void ModbusMessageWidget::update() } else { - auto resp = reinterpret_cast(_msg); + auto resp = reinterpret_cast(_mm); const auto length = resp->isValid() ? formatByteValue(_dataDisplayMode, resp->length()) : "?"; const auto data = resp->isValid() ? formatByteArray(_dataDisplayMode, resp->data()) : "???"; addItem(tr("Response Data Length: %1").arg(length)); @@ -436,9 +436,9 @@ void ModbusMessageWidget::update() break; case QModbusPdu::MaskWriteRegister: - if(_msg->isRequest()) + if(_mm->isRequest()) { - auto req = reinterpret_cast(_msg); + auto req = reinterpret_cast(_mm); const auto address = req->isValid() ? formatWordValue(_dataDisplayMode, req->address()) : "??"; const auto andMask = req->isValid() ? formatWordValue(_dataDisplayMode, req->andMask()) : "??"; const auto orMask = req->isValid() ? formatWordValue(_dataDisplayMode, req->orMask()) : "??"; @@ -448,7 +448,7 @@ void ModbusMessageWidget::update() } else { - auto resp = reinterpret_cast(_msg); + auto resp = reinterpret_cast(_mm); const auto address = resp->isValid() ? formatWordValue(_dataDisplayMode, resp->address()) : "??"; const auto andMask = resp->isValid() ? formatWordValue(_dataDisplayMode, resp->andMask()) : "??"; const auto orMask = resp->isValid() ? formatWordValue(_dataDisplayMode, resp->orMask()) : "??"; @@ -459,9 +459,9 @@ void ModbusMessageWidget::update() break; case QModbusPdu::ReadWriteMultipleRegisters: - if(_msg->isRequest()) + if(_mm->isRequest()) { - auto req = reinterpret_cast(_msg); + auto req = reinterpret_cast(_mm); const auto readStartAddr = req->isValid() ? formatWordValue(_dataDisplayMode, req->readStartAddress()) : "??"; const auto readLength = req->isValid() ? formatWordValue(_dataDisplayMode, req->readLength()) : "??"; const auto writeStartAddr = req->isValid() ? formatWordValue(_dataDisplayMode, req->writeStartAddress()) : "??"; @@ -477,7 +477,7 @@ void ModbusMessageWidget::update() } else { - auto resp = reinterpret_cast(_msg); + auto resp = reinterpret_cast(_mm); const auto byteCount = resp->isValid() ? formatByteValue(_dataDisplayMode, resp->byteCount()): "?"; const auto values = resp->isValid() ? formatWordArray(_dataDisplayMode, resp->values(), _byteOrder) : "???"; addItem(tr("Byte Count: %1").arg(byteCount)); @@ -486,15 +486,15 @@ void ModbusMessageWidget::update() break; case QModbusPdu::ReadFifoQueue: - if(_msg->isRequest()) + if(_mm->isRequest()) { - auto req = reinterpret_cast(_msg); + auto req = reinterpret_cast(_mm); const auto fifoAddr = req->isValid() ? formatWordValue(_dataDisplayMode, req->fifoAddress()) : "??"; addItem(tr("FIFO Point Address: %1").arg(fifoAddr)); } else { - auto resp = reinterpret_cast(_msg); + auto resp = reinterpret_cast(_mm); const auto byteCount = resp->isValid() ? formatByteValue(_dataDisplayMode, resp->byteCount()) : "?"; const auto fifoCount = resp->isValid() ? formatByteValue(_dataDisplayMode, resp->fifoCount()) : "?"; const auto fifoValue = resp->isValid() ? formatWordArray(_dataDisplayMode, resp->fifoValue(), _byteOrder) : "???"; @@ -506,7 +506,7 @@ void ModbusMessageWidget::update() default: { - const auto data = _msg->isValid() ? formatByteArray(_dataDisplayMode, _msg->rawData()) : "???"; + const auto data = _mm->isValid() ? formatByteArray(_dataDisplayMode, _mm->rawData()) : "???"; addItem(tr("Data: %1").arg(data)); } break; diff --git a/omodscan/controls/modbusmessagewidget.h b/omodscan/controls/modbusmessagewidget.h index 25fc53b..a0ddb72 100644 --- a/omodscan/controls/modbusmessagewidget.h +++ b/omodscan/controls/modbusmessagewidget.h @@ -34,7 +34,7 @@ class ModbusMessageWidget : public QListWidget ByteOrder _byteOrder; DataDisplayMode _dataDisplayMode; bool _showTimestamp; - const ModbusMessage* _msg; + const ModbusMessage* _mm; }; #endif // MODBUSMESSAGEWIDGET_H diff --git a/omodscan/dialogs/dialogmsgparser.cpp b/omodscan/dialogs/dialogmsgparser.cpp index 639fa97..0bf000c 100644 --- a/omodscan/dialogs/dialogmsgparser.cpp +++ b/omodscan/dialogs/dialogmsgparser.cpp @@ -41,7 +41,6 @@ DialogMsgParser::~DialogMsgParser() /// void DialogMsgParser::on_awake() { - //ui->rtu->setVisible(ui->buttonAdu->isChecked()); ui->deviceIdIncluded->setVisible(ui->buttonPdu->isChecked()); ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(!ui->bytesData->isEmpty()); } @@ -61,9 +60,9 @@ void DialogMsgParser::on_hexView_toggled(bool checked) /// void DialogMsgParser::accept() { - if(_mm) delete _mm; - auto data = ui->bytesData->value(); + if(data.isEmpty()) return; + ModbusMessage::Type type = ModbusMessage::Adu; auto protocol = QModbusAdu::Tcp; int checksum = 0; @@ -85,6 +84,7 @@ void DialogMsgParser::accept() data = data.left(data.size() - 2); } + if(_mm) delete _mm; _mm = ModbusMessage::parse(data, type, protocol, ui->request->isChecked(), checksum); ui->info->setModbusMessage(_mm); } diff --git a/omodscan/dialogs/dialogmsgparser.ui b/omodscan/dialogs/dialogmsgparser.ui index 7838454..781e6a8 100644 --- a/omodscan/dialogs/dialogmsgparser.ui +++ b/omodscan/dialogs/dialogmsgparser.ui @@ -33,9 +33,6 @@ false - - false - @@ -52,9 +49,6 @@ false - - false - From b9421cc0d845a833fb1616b67f5e939ce7d0bd31 Mon Sep 17 00:00:00 2001 From: sanny32 Date: Tue, 10 Oct 2023 17:00:58 +0300 Subject: [PATCH 72/90] Correct ui behavior --- omodscan/controls/bytelisttextedit.cpp | 6 ++++++ omodscan/dialogs/dialogmsgparser.ui | 6 ++++++ 2 files changed, 12 insertions(+) diff --git a/omodscan/controls/bytelisttextedit.cpp b/omodscan/controls/bytelisttextedit.cpp index edac53b..67ba1d2 100644 --- a/omodscan/controls/bytelisttextedit.cpp +++ b/omodscan/controls/bytelisttextedit.cpp @@ -149,6 +149,12 @@ void ByteListTextEdit::keyPressEvent(QKeyEvent *e) return; } + if(e->key() == Qt::Key_Enter || + e->key() == Qt::Key_Return) + { + return; + } + int pos = 0; auto text = toPlainText() + e->text(); const auto state = _validator->validate(text, pos); diff --git a/omodscan/dialogs/dialogmsgparser.ui b/omodscan/dialogs/dialogmsgparser.ui index 781e6a8..910c6b0 100644 --- a/omodscan/dialogs/dialogmsgparser.ui +++ b/omodscan/dialogs/dialogmsgparser.ui @@ -146,6 +146,12 @@ Qt::NoContextMenu + + QAbstractItemView::NoEditTriggers + + + QAbstractItemView::NoSelection + true From 5ba8f6fa2aaf728e36c97071e47b28d8ded4ef23 Mon Sep 17 00:00:00 2001 From: sanny32 Date: Tue, 10 Oct 2023 17:12:29 +0300 Subject: [PATCH 73/90] Correct ui view --- omodscan/dialogs/dialogmsgparser.ui | 3 +++ 1 file changed, 3 insertions(+) diff --git a/omodscan/dialogs/dialogmsgparser.ui b/omodscan/dialogs/dialogmsgparser.ui index 910c6b0..d9af7aa 100644 --- a/omodscan/dialogs/dialogmsgparser.ui +++ b/omodscan/dialogs/dialogmsgparser.ui @@ -149,6 +149,9 @@ QAbstractItemView::NoEditTriggers + + true + QAbstractItemView::NoSelection From e5a75742c5874bda31370b1e7b5bf987d515b314 Mon Sep 17 00:00:00 2001 From: ananev-aa Date: Tue, 10 Oct 2023 18:59:51 +0300 Subject: [PATCH 74/90] Correct ui view --- omodscan/dialogs/dialogmsgparser.ui | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/omodscan/dialogs/dialogmsgparser.ui b/omodscan/dialogs/dialogmsgparser.ui index d9af7aa..a128bb0 100644 --- a/omodscan/dialogs/dialogmsgparser.ui +++ b/omodscan/dialogs/dialogmsgparser.ui @@ -18,6 +18,9 @@ + + padding: 4px; + PDU Message @@ -33,10 +36,30 @@ false + + true + + + + + + + Qt::Horizontal + + + + + + + Qt::Vertical + + + padding: 4px; + ADU Message @@ -49,6 +72,9 @@ false + + true + From 02f9f4c7cb5bd4e44fc4dbc3bb29d77541e9000c Mon Sep 17 00:00:00 2001 From: ananev-aa Date: Tue, 10 Oct 2023 20:24:32 +0300 Subject: [PATCH 75/90] Correct build under 5.15.2 --- omodscan/qmodbusadu.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/omodscan/qmodbusadu.h b/omodscan/qmodbusadu.h index 38ccbb8..5420c12 100644 --- a/omodscan/qmodbusadu.h +++ b/omodscan/qmodbusadu.h @@ -53,7 +53,7 @@ class QModbusAdu void setData(const QByteArray& data) { _data = data; - _pdu.setFunctionCode(QModbusPdu::FunctionCode(_data[7])); + _pdu.setFunctionCode(QModbusPdu::FunctionCode((quint8)_data[7])); if(_type == Rtu) _pdu.setData(_data.mid(8, _data.size() - 10)); else From e8b797e669e07cec0a7bc0380a5b3d2978e5694c Mon Sep 17 00:00:00 2001 From: ananev-aa Date: Tue, 10 Oct 2023 20:24:58 +0300 Subject: [PATCH 76/90] Correct text capture (added Tx and Rx marks) --- omodscan/controls/outputwidget.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/omodscan/controls/outputwidget.cpp b/omodscan/controls/outputwidget.cpp index 3a6a2ad..69adb66 100644 --- a/omodscan/controls/outputwidget.cpp +++ b/omodscan/controls/outputwidget.cpp @@ -824,7 +824,8 @@ void OutputWidget::updateLogView(bool request, int server, const QModbusPdu& pdu auto msg = ui->logView->addItem(pdu, server, QDateTime::currentDateTime(), request); if(captureMode() == CaptureMode::TextCapture && msg != nullptr) { - const auto str = QString("%1 %2 %3").arg( + const auto str = QString("%1: %2 %3 %4").arg( + (msg->isRequest()? "Tx" : "Rx"), msg->timestamp().toString(Qt::ISODateWithMs), (msg->isRequest()? "<<" : ">>"), msg->toString(DataDisplayMode::Hex)); From f6064b367de1cc172acf797d19dcbb260fc42a53 Mon Sep 17 00:00:00 2001 From: ananev-aa Date: Tue, 10 Oct 2023 20:45:29 +0300 Subject: [PATCH 77/90] Added color setting for error status text --- omodscan/controls/modbusmessagewidget.cpp | 17 ++++++++++++++--- omodscan/controls/modbusmessagewidget.h | 3 +++ omodscan/controls/outputwidget.cpp | 1 + 3 files changed, 18 insertions(+), 3 deletions(-) diff --git a/omodscan/controls/modbusmessagewidget.cpp b/omodscan/controls/modbusmessagewidget.cpp index da2142d..0c99601 100644 --- a/omodscan/controls/modbusmessagewidget.cpp +++ b/omodscan/controls/modbusmessagewidget.cpp @@ -9,6 +9,7 @@ /// ModbusMessageWidget::ModbusMessageWidget(QWidget *parent) : QListWidget(parent) + ,_statusClr(Qt::red) ,_byteOrder(ByteOrder::LittleEndian) ,_dataDisplayMode(DataDisplayMode::Decimal) ,_showTimestamp(true) @@ -85,6 +86,16 @@ void ModbusMessageWidget::setShowTimestamp(bool on) update(); } +/// +/// \brief ModbusMessageWidget::setStatusColor +/// \param clr +/// +void ModbusMessageWidget::setStatusColor(const QColor& clr) +{ + _statusClr = clr; + update(); +} + /// /// \brief ModbusMessageWidget::modbusMessage /// \return @@ -117,9 +128,9 @@ void ModbusMessageWidget::update() if(!_mm->isValid()) { if(_mm->isRequest()) - addItem(tr("*** INVALID MODBUS REQUEST ***")); + addItem(tr("*** INVALID MODBUS REQUEST ***").arg(_statusClr.name())); else if(!_mm->isException()) - addItem(tr("*** INVALID MODBUS RESPONSE ***")); + addItem(tr("*** INVALID MODBUS RESPONSE ***").arg(_statusClr.name())); } auto addChecksum = [&]{ @@ -133,7 +144,7 @@ void ModbusMessageWidget::update() else { const auto calcChecksum = formatWordValue(_dataDisplayMode, _mm->calcChecksum()); - addItem(tr("Checksum: %1 (Expected: %2)").arg(checksum, calcChecksum)); + addItem(tr("Checksum: %1 (Expected: %2)").arg(checksum, calcChecksum, _statusClr.name())); } } }; diff --git a/omodscan/controls/modbusmessagewidget.h b/omodscan/controls/modbusmessagewidget.h index a0ddb72..7a3c1a6 100644 --- a/omodscan/controls/modbusmessagewidget.h +++ b/omodscan/controls/modbusmessagewidget.h @@ -27,10 +27,13 @@ class ModbusMessageWidget : public QListWidget bool showTimestamp() const; void setShowTimestamp(bool on); + void setStatusColor(const QColor& clr); + private: void update(); private: + QColor _statusClr; ByteOrder _byteOrder; DataDisplayMode _dataDisplayMode; bool _showTimestamp; diff --git a/omodscan/controls/outputwidget.cpp b/omodscan/controls/outputwidget.cpp index 69adb66..7ac4274 100644 --- a/omodscan/controls/outputwidget.cpp +++ b/omodscan/controls/outputwidget.cpp @@ -478,6 +478,7 @@ void OutputWidget::setStatusColor(const QColor& clr) auto pal = ui->labelStatus->palette(); pal.setColor(QPalette::WindowText, clr); ui->labelStatus->setPalette(pal); + ui->modbusMsg->setStatusColor(clr); } /// From 40dc45c99c8ec6a25ecedd94364c1d6b4fe1afa7 Mon Sep 17 00:00:00 2001 From: ananev-aa Date: Tue, 10 Oct 2023 20:45:47 +0300 Subject: [PATCH 78/90] Fix access violation bug --- omodscan/modbusmessages/modbusmessage.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/omodscan/modbusmessages/modbusmessage.h b/omodscan/modbusmessages/modbusmessage.h index 75a479b..3343878 100644 --- a/omodscan/modbusmessages/modbusmessage.h +++ b/omodscan/modbusmessages/modbusmessage.h @@ -279,7 +279,7 @@ class ModbusMessage switch(_type) { case Adu: - return _data.size() - 8; + return qMax(0, _data.size() - 8); case Pdu: return _data.size(); @@ -291,10 +291,10 @@ class ModbusMessage switch(_type) { case Adu: - return _data[8 + idx]; + return idx < _data.size() - 8 ? _data.at(8 + idx) : 0; case Pdu: - return _data[idx]; + return idx < _data.size() ? _data.at(idx) : 0; } return 0; } From f0b325fd9a292ab68b7d3c677c784db148a32bcd Mon Sep 17 00:00:00 2001 From: sanny32 Date: Wed, 11 Oct 2023 08:29:27 +0300 Subject: [PATCH 79/90] Correct ByteListTextEdit behavior --- omodscan/controls/bytelisttextedit.cpp | 60 +++++++++++++++++--------- omodscan/controls/bytelisttextedit.h | 2 + omodscan/dialogs/dialogmsgparser.cpp | 19 ++++++++ omodscan/dialogs/dialogmsgparser.h | 1 + 4 files changed, 62 insertions(+), 20 deletions(-) diff --git a/omodscan/controls/bytelisttextedit.cpp b/omodscan/controls/bytelisttextedit.cpp index 67ba1d2..ecc8092 100644 --- a/omodscan/controls/bytelisttextedit.cpp +++ b/omodscan/controls/bytelisttextedit.cpp @@ -1,4 +1,5 @@ #include +#include #include "formatutils.h" #include "bytelisttextedit.h" @@ -86,25 +87,7 @@ ByteListTextEdit::InputMode ByteListTextEdit::inputMode() const void ByteListTextEdit::setInputMode(InputMode mode) { _inputMode = mode; - - if(_validator) - { - delete _validator; - _validator = nullptr; - } - - const auto sep = (_separator == ' ')? "\\s" : QString(_separator); - switch(mode) - { - case DecMode: - _validator =new QRegularExpressionValidator(QRegularExpression("(?:[0-9]{1,2}[" + sep + "]{0,1})*"), this); - break; - - case HexMode: - _validator = new QRegularExpressionValidator(QRegularExpression("(?:[0-9a-fA-F]{1,2}[" + sep + "]{0,1})*"), this); - break; - } - + updateValidator(); setValue(_value); } @@ -174,13 +157,26 @@ void ByteListTextEdit::keyPressEvent(QKeyEvent *e) } } +/// +/// \brief ByteListTextEdit::insertFromMimeData +/// \param source +/// +void ByteListTextEdit::insertFromMimeData(const QMimeData* source) +{ + int pos = 0; + auto text = source->text().trimmed(); + const auto state = _validator->validate(text, pos); + + if(state == QValidator::Acceptable) + QPlainTextEdit::insertFromMimeData(source); +} + /// /// \brief ByteListTextEdit::on_textChanged /// void ByteListTextEdit::on_textChanged() { QByteArray value; - switch(_inputMode) { case DecMode: @@ -250,3 +246,27 @@ void ByteListTextEdit::updateValue() break; } } + +/// +/// \brief ByteListTextEdit::updateValidator +/// +void ByteListTextEdit::updateValidator() +{ + if(_validator) + { + delete _validator; + _validator = nullptr; + } + + const auto sep = (_separator == ' ')? "\\s" : QString(_separator); + switch(_inputMode) + { + case DecMode: + _validator =new QRegularExpressionValidator(QRegularExpression("(?:[0-9]{1,2}[" + sep + "]{0,1})*"), this); + break; + + case HexMode: + _validator = new QRegularExpressionValidator(QRegularExpression("(?:[0-9a-fA-F]{1,2}[" + sep + "]{0,1})*"), this); + break; + } +} diff --git a/omodscan/controls/bytelisttextedit.h b/omodscan/controls/bytelisttextedit.h index b589af7..595e11a 100644 --- a/omodscan/controls/bytelisttextedit.h +++ b/omodscan/controls/bytelisttextedit.h @@ -40,12 +40,14 @@ class ByteListTextEdit : public QPlainTextEdit protected: void focusOutEvent(QFocusEvent* e) override; void keyPressEvent(QKeyEvent* e) override; + void insertFromMimeData(const QMimeData* source) override; private slots: void on_textChanged(); private: void updateValue(); + void updateValidator(); private: InputMode _inputMode; diff --git a/omodscan/dialogs/dialogmsgparser.cpp b/omodscan/dialogs/dialogmsgparser.cpp index 0bf000c..264b482 100644 --- a/omodscan/dialogs/dialogmsgparser.cpp +++ b/omodscan/dialogs/dialogmsgparser.cpp @@ -55,6 +55,25 @@ void DialogMsgParser::on_hexView_toggled(bool checked) ui->info->setDataDisplayMode(checked ? DataDisplayMode::Hex : DataDisplayMode::Decimal); } +/// +/// \brief DialogMsgParser::on_bytesData_valueChanged +/// \param value +/// +void DialogMsgParser::on_bytesData_valueChanged(const QByteArray& value) +{ + if(value.size() < 3) + { + if(value.isEmpty()) + ui->info->clear(); + + return; + } + + const auto data = value.left(value.size() - 2); + const int checksum = makeWord(value[value.size() - 1], value[value.size() - 2], ByteOrder::LittleEndian); + ui->checksumIncluded->setChecked(QModbusAdu::calculateCRC(data, data.size()) == checksum); +} + /// /// \brief DialogMsgParser::accept /// diff --git a/omodscan/dialogs/dialogmsgparser.h b/omodscan/dialogs/dialogmsgparser.h index 21fb970..cce4d9e 100644 --- a/omodscan/dialogs/dialogmsgparser.h +++ b/omodscan/dialogs/dialogmsgparser.h @@ -25,6 +25,7 @@ class DialogMsgParser : public QDialog private slots: void on_awake(); void on_hexView_toggled(bool); + void on_bytesData_valueChanged(const QByteArray& value); private: Ui::DialogMsgParser *ui; From 14d5fd3699bdef9cc5e4217cb35b82525efdadc0 Mon Sep 17 00:00:00 2001 From: sanny32 Date: Wed, 11 Oct 2023 08:37:14 +0300 Subject: [PATCH 80/90] Correct ByteListTextEdit behavior --- omodscan/controls/bytelisttextedit.cpp | 61 +++++++++++++++----------- omodscan/controls/bytelisttextedit.h | 2 +- 2 files changed, 37 insertions(+), 26 deletions(-) diff --git a/omodscan/controls/bytelisttextedit.cpp b/omodscan/controls/bytelisttextedit.cpp index ecc8092..66dbfae 100644 --- a/omodscan/controls/bytelisttextedit.cpp +++ b/omodscan/controls/bytelisttextedit.cpp @@ -87,7 +87,25 @@ ByteListTextEdit::InputMode ByteListTextEdit::inputMode() const void ByteListTextEdit::setInputMode(InputMode mode) { _inputMode = mode; - updateValidator(); + + if(_validator) + { + delete _validator; + _validator = nullptr; + } + + const auto sep = (_separator == ' ')? "\\s" : QString(_separator); + switch(_inputMode) + { + case DecMode: + _validator =new QRegularExpressionValidator(QRegularExpression("(?:[0-9]{1,2}[" + sep + "]{0,1})*"), this); + break; + + case HexMode: + _validator = new QRegularExpressionValidator(QRegularExpression("(?:[0-9a-fA-F]{1,2}[" + sep + "]{0,1})*"), this); + break; + } + setValue(_value); } @@ -157,6 +175,20 @@ void ByteListTextEdit::keyPressEvent(QKeyEvent *e) } } +/// +/// \brief ByteListTextEdit::canInsertFromMimeData +/// \param source +/// \return +/// +bool ByteListTextEdit::canInsertFromMimeData(const QMimeData* source) const +{ + int pos = 0; + auto text = source->text().trimmed(); + const auto state = _validator->validate(text, pos); + + return state == QValidator::Acceptable; +} + /// /// \brief ByteListTextEdit::insertFromMimeData /// \param source @@ -168,7 +200,10 @@ void ByteListTextEdit::insertFromMimeData(const QMimeData* source) const auto state = _validator->validate(text, pos); if(state == QValidator::Acceptable) + { QPlainTextEdit::insertFromMimeData(source); + updateValue(); + } } /// @@ -246,27 +281,3 @@ void ByteListTextEdit::updateValue() break; } } - -/// -/// \brief ByteListTextEdit::updateValidator -/// -void ByteListTextEdit::updateValidator() -{ - if(_validator) - { - delete _validator; - _validator = nullptr; - } - - const auto sep = (_separator == ' ')? "\\s" : QString(_separator); - switch(_inputMode) - { - case DecMode: - _validator =new QRegularExpressionValidator(QRegularExpression("(?:[0-9]{1,2}[" + sep + "]{0,1})*"), this); - break; - - case HexMode: - _validator = new QRegularExpressionValidator(QRegularExpression("(?:[0-9a-fA-F]{1,2}[" + sep + "]{0,1})*"), this); - break; - } -} diff --git a/omodscan/controls/bytelisttextedit.h b/omodscan/controls/bytelisttextedit.h index 595e11a..b2d3058 100644 --- a/omodscan/controls/bytelisttextedit.h +++ b/omodscan/controls/bytelisttextedit.h @@ -40,6 +40,7 @@ class ByteListTextEdit : public QPlainTextEdit protected: void focusOutEvent(QFocusEvent* e) override; void keyPressEvent(QKeyEvent* e) override; + bool canInsertFromMimeData(const QMimeData* source) const override; void insertFromMimeData(const QMimeData* source) override; private slots: @@ -47,7 +48,6 @@ private slots: private: void updateValue(); - void updateValidator(); private: InputMode _inputMode; From 5f9eba11b0992ba55b1b53312d0d78b508d56b30 Mon Sep 17 00:00:00 2001 From: sanny32 Date: Wed, 11 Oct 2023 08:43:34 +0300 Subject: [PATCH 81/90] Correct ui of Dialog User Msg --- omodscan/dialogs/dialogusermsg.ui | 31 +++++++++++++++++-------------- 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/omodscan/dialogs/dialogusermsg.ui b/omodscan/dialogs/dialogusermsg.ui index 73a8a9a..42931f6 100644 --- a/omodscan/dialogs/dialogusermsg.ui +++ b/omodscan/dialogs/dialogusermsg.ui @@ -56,6 +56,12 @@ + + + 200 + 0 + + Qt::NoContextMenu @@ -85,7 +91,7 @@ - + 0 0 @@ -116,9 +122,6 @@ Qt::Horizontal - - QSizePolicy::Expanding - 40 @@ -234,16 +237,6 @@ - - FunctionCodeComboBox - QComboBox -
functioncodecombobox.h
-
- - NumericLineEdit - QLineEdit -
numericlineedit.h
-
ModbusMessageWidget QListWidget @@ -254,6 +247,16 @@ QPlainTextEdit
bytelisttextedit.h
+ + FunctionCodeComboBox + QComboBox +
functioncodecombobox.h
+
+ + NumericLineEdit + QLineEdit +
numericlineedit.h
+
radioButtonDecimal From 820a72b27482b876a0700f75d1dfa43fca121450 Mon Sep 17 00:00:00 2001 From: sanny32 Date: Wed, 11 Oct 2023 12:23:55 +0300 Subject: [PATCH 82/90] Correct ui view --- omodscan/controls/modbusmessagewidget.cpp | 3 +-- omodscan/controls/outputwidget.ui | 3 +++ omodscan/htmldelegate.cpp | 6 +++--- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/omodscan/controls/modbusmessagewidget.cpp b/omodscan/controls/modbusmessagewidget.cpp index 0c99601..612f212 100644 --- a/omodscan/controls/modbusmessagewidget.cpp +++ b/omodscan/controls/modbusmessagewidget.cpp @@ -14,7 +14,6 @@ ModbusMessageWidget::ModbusMessageWidget(QWidget *parent) ,_dataDisplayMode(DataDisplayMode::Decimal) ,_showTimestamp(true) ,_mm(nullptr) - { setItemDelegate(new HtmlDelegate(this)); setEditTriggers(QAbstractItemView::NoEditTriggers); @@ -149,7 +148,7 @@ void ModbusMessageWidget::update() } }; - addItem(tr("Type: %1").arg(_mm->isRequest() ? tr("Tx Message") : tr("Rx Message"))); + addItem(tr("Type: %1").arg(_mm->isRequest() ? tr("Request (Tx)") : tr("Response (Rx)"))); if(_showTimestamp) addItem(tr("Timestamp: %1").arg(_mm->timestamp().toString(Qt::ISODateWithMs))); if(_mm->type() == ModbusMessage::Adu) diff --git a/omodscan/controls/outputwidget.ui b/omodscan/controls/outputwidget.ui index 7327d3f..0314a85 100644 --- a/omodscan/controls/outputwidget.ui +++ b/omodscan/controls/outputwidget.ui @@ -128,6 +128,9 @@ Qt::Vertical + + true + diff --git a/omodscan/htmldelegate.cpp b/omodscan/htmldelegate.cpp index 2dbb32e..08fddad 100644 --- a/omodscan/htmldelegate.cpp +++ b/omodscan/htmldelegate.cpp @@ -10,7 +10,7 @@ /// \param parent /// HtmlDelegate::HtmlDelegate(QObject* parent) - :QStyledItemDelegate(parent) + : QStyledItemDelegate(parent) { } @@ -41,7 +41,7 @@ void HtmlDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, QTextDocument doc; doc.setHtml(opt.text); - doc.setDocumentMargin(0); + doc.setDocumentMargin(2); doc.setDefaultFont(opt.font); doc.setDefaultTextOption(textOption); doc.setTextWidth(opt.rect.width()); @@ -82,7 +82,7 @@ QSize HtmlDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelInd QTextDocument doc; doc.setHtml(opt.text); - doc.setDocumentMargin(0); + doc.setDocumentMargin(2); doc.setDefaultFont(opt.font); if(opt.features & QStyleOptionViewItem::WrapText) From e9f59fc8925dc7b617ac6d1e468352ed990260c8 Mon Sep 17 00:00:00 2001 From: sanny32 Date: Wed, 11 Oct 2023 12:26:54 +0300 Subject: [PATCH 83/90] Correct ui view --- omodscan/controls/outputwidget.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/omodscan/controls/outputwidget.cpp b/omodscan/controls/outputwidget.cpp index 7ac4274..88f8557 100644 --- a/omodscan/controls/outputwidget.cpp +++ b/omodscan/controls/outputwidget.cpp @@ -532,7 +532,7 @@ void OutputWidget::setStatus(const QString& status) } else { - const auto info = QString("** %1 **").arg(status); + const auto info = QString("*** %1 ***").arg(status); if(info != ui->labelStatus->text()) ui->labelStatus->setText(info); } From bf9243bb6519d98dee9001a89d212895c15f4662 Mon Sep 17 00:00:00 2001 From: sanny32 Date: Wed, 11 Oct 2023 16:09:55 +0300 Subject: [PATCH 84/90] Removed unused include --- omodscan/controls/outputwidget.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/omodscan/controls/outputwidget.cpp b/omodscan/controls/outputwidget.cpp index 88f8557..f336dc2 100644 --- a/omodscan/controls/outputwidget.cpp +++ b/omodscan/controls/outputwidget.cpp @@ -3,7 +3,6 @@ #include #include #include "formatutils.h" -#include "htmldelegate.h" #include "outputwidget.h" #include "modbusmessages.h" #include "ui_outputwidget.h" From a31863fab761944dc6fcff1f02e73942e15f0f62 Mon Sep 17 00:00:00 2001 From: sanny32 Date: Wed, 11 Oct 2023 16:29:02 +0300 Subject: [PATCH 85/90] Removed unused include --- omodscan/dialogs/dialogdisplaydefinition.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/omodscan/dialogs/dialogdisplaydefinition.h b/omodscan/dialogs/dialogdisplaydefinition.h index f3fc3bb..75cdc01 100644 --- a/omodscan/dialogs/dialogdisplaydefinition.h +++ b/omodscan/dialogs/dialogdisplaydefinition.h @@ -2,7 +2,7 @@ #define DIALOGDISPLAYDEFINITION_H #include "qfixedsizedialog.h" -#include "formmodsca.h" +#include "displaydefinition.h" namespace Ui { class DialogDisplayDefinition; From d850e637a9c6831b0da23a71af32431fb986a5a4 Mon Sep 17 00:00:00 2001 From: sanny32 Date: Thu, 12 Oct 2023 09:07:53 +0300 Subject: [PATCH 86/90] Translation updated --- omodscan/translations/omodscan_ru.qm | Bin 30468 -> 38780 bytes omodscan/translations/omodscan_ru.ts | 773 ++++++++++++++++++++------- 2 files changed, 592 insertions(+), 181 deletions(-) diff --git a/omodscan/translations/omodscan_ru.qm b/omodscan/translations/omodscan_ru.qm index 36d2d90cc2f214e7cf8b9e300df13a70bce7da84..02745295653abea491e52e0f73a76d8d61a51377 100644 GIT binary patch delta 10293 zcmb_h34Bvk_C878OVTt=DRdXgYinttEG=CqZCdC`OZSC+O`A|s+N2~Yn?i~#isD#^ zh`54`AfQO?AmGAu6a`V%K@k1x$fz@lfTEy(M+WD6c}Yl1Q(I=_7f)W^z4zR6&Ue0Z z?(NDeq8q!#Ed#8|Jwy~olrf8lok>(Mlt}h6QDOp7QZs&kn5g6kQI12-yiQcPlBnuU zL9R05`(YwYFwulR5)IoA`7TlZbz;_Hol(1q+4&5{BnWbq4>2DcB#OO3%n639H2q~_ zPDT;Uc$k>8RYWtT#9YFLX1+^o;5z;#>d40R@gV}vTckw&^qa;IP(n5u0JI%*{mQMSs>P_euPm?|Ti~X)Y1BXZ=7ltxnwjHRSX@;zJiN5-B8t z4CyDxGH>yTq7b6mQ1OLvTY;;Xb>a(e!TcsK@x_myBPv`a$fEbf*W^h=QD?-z7^V;f z>%}+D!oKQJ zmr0)C-zOiGyqDKXWR)|0(*U5_`PLars|K#nBZN^{QIwC-SbRK z{w4$>kJ)6{K;+k-*_LbrKrPI+qMsqRG6#-Yzd~ffn1c!x(clLKIW>%FuYVhg8<<0j zkqML_$muhg!+G&Ui!U-CcsCMdy~cd3{vHPH;c4)~9M50V5a;lkVjfk~AP&k9=fj;c|d*E8jBkYEwaE&65eR}&)`50uR5@hI1scITfp7xmZ?u!y6|4nJs z+s6@!G15WD_rS&Hq{BYNd*3{1p$@UFdrmrCoJthEK{}&vE^@zFTJJX#Y-^Mn_hB9j zdBhBI3y?0~eg;_EDP36_Ml{trL%PQM3Am_L`smei#PAL2#>22YE>rsC3JW$cS^Cz_ z&xneKN{>7}8TPLTP;uS5FIkfl!<4w9NH8^cShCP!9$9y_f0QC2ae8fd*oHX+vl8aynk zQ6P^aQf2ydEbKK=W_T|SiddQ9DAH|Cy=>`OAz$L4{G7!A+moiM(pzr z$}ayFi3JM>{tM(__KcBfMrOz;p4h+WssJv`$fa9V(v$!d&Nd{#!&OaJknvOInEftnj)R zh3WHkUf&h2Lv~ks{ab_mSI$+?KQtiZuN92#B%nD>!JdI5OP^PG@51r}M1thjLuTT6 zilR?2w$sp}@VoX3>h5kq&K|8u{5S!Q9(-Ccx&@I-|3snwsT{PiN1^#O5sV$H&=r0O zKKfiycOJhlZBWen@fo82n*=%V4aNMmfKqGca8xH?PmGz;1MSH+7@H=`pdRqWC22GK^wD)xNvAv%Cq#s1@=aPSC0mW)=s zCQ%b**D2oHj6lrTulP70ZOf{yif{A0h$gL6{B#B51HSk6TC5}dC&;P)_SUsWA?d2T z=fs=_?X2{kb1nddR^mPHF9>8^hIjonAY;}w@1@yRxYiQsz4iije%B5`hP4Ya{Qm_x zXr3Um77H>zT9D&Kf-L;I_iNAj0rQ)@+y5>`l1=u$^k@}4((HZt;2|X03MKszPZaW! zQhaO^AUaej&y&Ez`;|e%ryT?ao0YNS-@#55%3%SYgW*pohXt>Ki_R!V%0LgA9m+Aw zKLO3Gw7o13OdUF0SrYdVYUvtf$!-kqUnIzZ^OTxstXmT;$Tc;}y5T!e3ePDUW4}PD z`_lHaJj_~{rhM?sk3{ki<;I8vqA-*4`S+ud%G(8*bY1!8E)=*>M){WZIRx$l9<8$*%yl)(%VqS&9ao?$e`wfR7j3C2vRl(111!;b-8Ws-s zPKsBh{-i*!@&Ye`xW1vPw6s>FQ&j_v?Etq1<73zWOk^k*vf#8_p0Wu!TW$1 zmE~n{O~`cBk{cChtm{?lAGrzOTo&X&x#}@K<*mP}HgChYpfRd#hu7iRqPl#{go>N1 z`o3QPTthX!QWKAa~%Pa5(Iu?~4)(_H{~-E4TT+Sc2#2|L1#XARM@Gf$ygq zXA<3a+V@JC9=+jS{O`fX02xB_!q^VY3~f8BC=3qoLorMylf{f>GMH2*g$Bzpgl~~a z8e=jpG!M45MuywMBU?uVGIud4j2fRT;+QmyPhjFG)ivI?$XLrw)aw>lvK8g0*seu|VU4o<;Dm102&$~tEYNW| zx&`_gUB{IM+IB>5`Y&ziA2Z0-5>tLhw(xUP2ES`7%}=s%F%kcTEm*1T=HQ)ut)Y}j zIWz&$%tSOZn0TfDK}tu2lUyP3&diy>6(c5^TAd82@XgU{>W#I<=Groi$*ePpct}Ms zp_rcTfKeJ#gzs@oseR#WKt|2Pxfb-xo~x^wXKrfXBJ_ru`X;ST>v3Iw#LM66n%Y;0 z3s<1!es}6@pnN2(N#ya$Bw;I~?3)_rv=G0H#3vpb9gPujOfC(@^H_Wvg;_~JIPZ&e zW?F`Q`WSnP#M@uQ@oC`N)}UO2MQ7rw7h7~@Zh@x0Nyl+!U8BaNvFNn;nKL(PYINqV zth7z_AD_{sOOuf_yc5%~|51=xaPU~{uXChE+s5VvSp$lV+Uh2=Gf~f~CO_xVlyMB-Al}r#U5*(W8nk1{x&2Q3~Ew@i=+oDcWTK{(uy`zBk zy*;9~ck-W-r7#14i7cCHP7uo@KGn7^Cm#lQ#tG?P7xIbr|i^klR5;KVF4F%N1+P^HO`FBT>+S+7e)Ok%9aA9hMKk@>xi8 zF5B2-u=Gelio=NCB}lTmS=B)+Zmb>mXYf5F~JK_lt9sL zwc1RLq#*--;m|f@Fv);yBBBHQBSNJ-7%^w0TN5$%w!N#th6c`TSzND6kFGJ+8%?QE z3DNdyZ*H_|3>jQZ?xIFyi%y%$MU5QXEkuSpEDgs7c#h1*HVUx`-UvO+aJSDLih=yL zjQV=6(xS06nO$B*$LJZ45e{Yk_LNFz3Q-q4De#4Y9F0ZeTDiN0hd36FWNekFcP?yq zK!HEMqMbRof}CD0%R?{GP8<1%SG>K=^R#aud{joR$z(JE<62#h^zdt;i*w`_d4}fRAS_Jp1Go0+Rug_+FoL zQ#seoi*A+;aOx~G>JhBo(07hQcaXi0aXHbprz*($d!~jt)lRgxQx&>ey%{}LkKj18 zQy_D|3hA&n4}eS&;9|9(Ksr{ZU|waDL8#I_j-Zp?I~j>=Tl$PPHQx^qz| z6c-p8n=G8u%$@-@&S7U~?$d*y8>xvb9aOq&46?dZcH+P862w{P{q4;jdQ*?<^O@&3 zjCEau18|sdEA$zHC2j=beirdeB7DdkZ9^||!ikSgZ3RxZXf3QBjpDnPQd7@63#Yqo zrCtZ7a?3HEJxZG_JOVPUjstMle(UJA-qa(WZyh?iElXDSxD4ttgFP3$pj%4pdE29O zb<#wz{m^CQ50NQM4nBP6>OA!bX9fN#6`!D^p?e(aSkWAvuC;LhHzV**?)#7DDd|l?mBwM2vxW82wDQ`6X7ZTNHPw76wdXY zi_2Z^nsG>}&}pfDY2_f^++KQaZ_`xAd&%$Z|mQR(3hel!EJ1 zm{L@k0FMnd?`7UTzWXy-^oH7A)wLccb~*7*b%wB4Ivgz(&dK~8fP3u>nBxgMJdL=N z^*sN&QRUHre93aEGIKrGnm4vYy!t?Qb`H-`M( z3=jDZ-Dwv@$>(;JNn}wjA6BatH};BoJKdN#Gnemp zJ@Y*eK|9BDy}U)qci7R94@Er92U;DZ(Y~;V#v8 zlzz>&XJbQdyO@c$U(5_4{vU^%!2n#rhcO)f@!ulwODq$D6J9Y6lsS}zTmDLn3&J(s zK#U1v!tqX+&38MliyhZxox0;aO_6X>6Ca&1WXKS%pk!iZQ9%w@T$+vPUvr@%WEplCFP40p?@aJIreK7xb3;c}@3srPj$frW*C_gb3w^r)3P}_5j H)zbd}f`c9A delta 2867 zcmai0>0cCA7QJ0vRoz`(bO*3eP!MHD8%2>tkWE$*6aiU97TFYW16*Qkx440Zq1bf;ps$ZS01JRb;R2gREDR)2=Wgm$QywQ+lhJ zXj~{|6k(qMB4sq!5~bBs)}kXQP&Lh&i1;R*l-d+Frv7K>^TrY)?OcVzfba`mDTd9u zPo&G1F>I}j!)GW)9vTfUHY(x=)e)%^73nkxq+C)|SWY1FOIFoJej!S< zQvBxhE0OD$iq8&jk;Z+-U_yBP<}#jn;9h-!@iJTi4>pe(FK1_>(bt)M$W^khzV zb`l9n8GE$L7<+_i8)-{4{ufG5xLq95~U9rS>XO){XCK7d1u~vZ~ zC?|-G^lv3{tYnk7LwP+)*lA1uLo`8RYhvn9p+vT>%(#ZgvKPD4R|4ZEcIU|Vzyoa4 zg-0maMz%%J;UHTXlRTsl*2a`l!d}!)B^u_(-U)hz={M{>^HQR$cWfs;AnLwQ#(}Qv z>zsNx=oj|&O-JO(a{Uu_6Df*h^!Uj6XU>JNc5y*7aa?8{7t-K@aR(Rm(g}iz;9~sE z5Sl#~X9or+xN|AH&0x$i;LisNdnn`ZQ!+*#=F)2Rfsqwl&W!>b^etCh(?ryt;VRc* zBjZ|bPWybKiF>$Zad1M(_uQHb$XAHszExx1&xYGubqdPu;Evo!ASEBUro@*-87DZi zQ$3OO_$~xvF6ErL7z_Lzxr>8#pis`-r8x;iR=SwZK5t#=+Jxpo6G59L?CPDDnP{JOKR zvF-}LaZxz}y3U{6dmoZZcnsS>c?v{%4hlo>yRm0M~&_jwKpPK) z>e6m-!&ISqI=(ZNxC=GM5I|9*Wlq&;n9v=5iD_fi?1KFApKPR6h#8HXEX zjMQn(|70LWEA8{u$;iA)`=aGE#Jx(SH{L|Hb|Q1B4q8eR)lo|LKlzl{J+lR3nJ@Mm zaR#0Cv}iOuK<8}}2dQAgjC?UZc1pXL&iy3acV!PKQLFUD2Isk?cz)uX{%suiYO9ST>Cd}F z)kLv=7Vj_T5{-zp_!yH<s=XJ#{^HK;Gl_>WqC*y3s+pq3;CTrn_adveN|y z!har7GRCaY4S#BeXx8cCO)NT^Sy#LqV}rYH&ZjZpAbP#7ekY9HJw$il>y56p#vdEM@!D(E7#HCq zN^Xf?OZH;|8*9cS3CeKRNy^WTRoF{Mv%MQ1W)&zJpJeyfNy`F;NHLRB8(&R!5E~u; HlEwc4!VfG9 diff --git a/omodscan/translations/omodscan_ru.ts b/omodscan/translations/omodscan_ru.ts index 57c2a29..f1b11ee 100644 --- a/omodscan/translations/omodscan_ru.ts +++ b/omodscan/translations/omodscan_ru.ts @@ -30,27 +30,27 @@ CsvExporter - + Device Id Узел - + Start Address Начальный адрес - + Length Количество - + Point Type Тип регистров - + Registers on Query Количество регистров в запросе @@ -165,7 +165,7 @@ - + Scan Сканировать @@ -200,12 +200,12 @@ Показывать только корректные ответы - + Stop Стоп - + Pdf files (*.pdf);;CSV files (*.csv) Pdf файлы (*.pdf);;CSV файлы (*.csv) @@ -214,7 +214,7 @@ Pdf файлы (*.pdf) - + No connection to MODBUS device! Нет соединения с MODBUS устройством! @@ -384,37 +384,47 @@ Настройки отображения - + Scan Rate: Частота опроса: - + (msecs) (мсек) - + + Log View Limit: + Лимит лога: + + + + (rows) + (строки) + + + Modbus Data Настройки Modbus - + Slave Address: Адрес устройства: - + Point Type: Тип регистров: - + Point Address: Начальный адрес: - + Length: Количество: @@ -427,34 +437,52 @@ - + + Slave Device: + Устройство: + + + Address: Адрес: - + Set Values to 0 Установить в 0 - + Set Values to 1 Установить в 1 - + Length: Количество: - Address: %1 - Адрес: %1 + Адрес: %1 - Length: %1 - Количество: %1 + Количество: %1 + + + + Address: <b>%1</b> + Адрес: <b>%1</b> + + + + Length: <b>%1</b> + Количество: <b>%1</b> + + + + Slave Device: <b>%1</b> + Устройство: <b>%1</b> @@ -465,34 +493,52 @@ - + + Slave Device: + Устройство: + + + Length: Количество: - + Set Random Values Установить случайные - + Set Values to 0 Установить в 0 - + Address: Адрес: - Address: %1 - Адрес: %1 + Адрес: %1 - Length: %1 - Количество: %1 + Количество: %1 + + + + Address: <b>%1</b> + Адрес: <b>%1</b> + + + + Length: <b>%1</b> + Количество: <b>%1</b> + + + + Slave Device: <b>%1</b> + Устройство: <b>%1</b> @@ -551,161 +597,161 @@ Диапазон IP адресов - - - + + + from с - - - + + + to по - + Subnet Mask Маска подсети - + Port Range Диапазон портов - + Start Scan Сканировать - + <html><head/><body><p><span style=" font-weight:700;">Scanning:</span></p></body></html> <html><head/><body><p><span style=" font-weight:700;">Сканирование:</span></p></body></html> - + Address: Адрес: - + Port: Порт: - + Baud Rate: Скорость бит/с: - + Data Bits: Биты данных: - + Parity: Четность: - + Stop Bits: Стоповые биты: - + Device Id: Узел: - + Scan Time Вермя сканирования - + Data Bits Биты данных - + Parity Четность - + None Нет - + Odd Нечет - + Even Чёт - + Stop Bits Стоповые биты - + Device Id Узел - + Modbus Request Запрос Modbus - + Function Функция - + Address Адрес - + Length Количество - + Response Timeout Таймаут ответа - + msec мсек - + <html><head/><body><p><span style=" font-weight:700;">Scan Results:</span></p></body></html> <html><head/><body><p><span style=" font-weight:700;">Результаты:</span></p></body></html> - + PORT: Device Id (serial port settings) Порт: Узел (параметры порта) - + Clear Results Очистить результаты @@ -770,41 +816,90 @@ Узел: - + Baud Rate: %1 Скорость бит/с: %1 - + Data Bits: %1 Биты данных: %1 - + Parity: %1 Четность: %1 - + Stop Bits: %1 Стоповые биты: %1 - + Address: %1 Адрес: %1 - + Port: %1 Порт: %1 - + Device Id: %1 Узел: %1 + + DialogMsgParser + + + Modbus Message Parser + Анализатор сообщений Modbus + + + + PDU Message + PDU сообщение + + + + ADU Message + ADU сообщение + + + + Hex View + Шестнадцатиричный режим + + + + Request + Запрос + + + + Device Id included + Устройство + + + + Checksum included + Контрольная сумма + + + + Enter bytes value separated by spaces + Введите значение в байтах, разделенное пробелами + + + + + Parse + Анализ + + DialogPrintSettings @@ -1036,40 +1131,55 @@ single-point write functions 05 and 06.) Пользовательская команда - + Slave Address: Адрес устройства: - + Function: Функция: - + Show Data in Отображать данные в формате - + Decimal Десятичный - + Hex Шестандцатиричный - + Send Data: Данные запроса: - + + Enter bytes value separated by spaces + Введите значение в байтах, разделенное пробелами + + + Response Buffer Ответ + + + Send + Отправить + + + + No connection to device + Нет подключения к устройству + DialogWindowsManager @@ -1229,53 +1339,57 @@ single-point write functions 05 and 06.) Тип регистров MODBUS - + Data Uninitialized Данные не инициализированы - + Device Id: %1 Узел: %1 - + Address: %1 Length: %2 Адрес: %1 Количество: %2 - + MODBUS Point Type: %1 Тип регистров MODBUS: %1 - + Number of Polls: %1 Valid Slave Responses: %2 Количество запросов: %1 Корректных ответов устройства: %2 - + + No Scan: Invalid Data Length Specified + Нет опроса: указана недопустимая длина данных + + + Device NOT CONNECTED! Устройство НЕ ПОДКЛЮЧЕНО! - Invalid Data Length Specified - Указана недопустимая длина данных + Указана недопустимая длина данных - + No Responses from Slave Device Нет ответа от устройства - + Received Invalid Response MODBUS Query Получен некорректный ответ на запрос MODBUS @@ -1374,7 +1488,7 @@ Valid Slave Responses: %2 - + Byte Order Порядок байтов @@ -1384,337 +1498,343 @@ Valid Slave Responses: %2 Расширенные параметры - + View Вид - + Config Конфигурация - + Colors Цвета - + Language Язык - + Window Окно - + Help Помощь - - + + Toolbar Панель инструментов - + Display Bar Панель отображения - + New Новый - + Open... Открыть... - + Close Закрыть - + Save Сохранить - + Save As... Сохранить как... - + Print... Печать... - + Print Setup... Настройка печати... - + Recent File Последние файлы - + Exit Выход - + Connect Подключиться - + Disconnect Отключиться - + Enable Вкл - + Disable Выкл - + Save Config Сохранить конфиг - + Restore Now Восстановить конфиг - + Quick Connect Быстрое подключение - + Data Definition Настройки отображения - + Show Data Данные - + Show Traffic Трафик - + Binary Двоичный - + Hex Шестандцатиричный - + Unsigned Decimal Беззнаковый десятичный - + Integer Целый - + Floating Pt С плавающей точкой - + Swapped FP Перевернутое с плавающей точкой - + Dbl Float Двойной точности - + Swapped Dbl Перевернутое двойной точности - + Hex Addresses Шестнадцатиричные адреса - + Force Coils Предустановка coils - + Preset Regs Предустановка регистров - + Mask Write Запись по маске - + User Msg Пользовательская команда - + Text Capture Захват в файл - + Capture Off Остановить захват - + Reset Ctrs Сброс счетчиков - + Status Bar Строка состояния - + Dsiplay Bar Панель отображения - + Background Задний план - + Foreground Передний план - + Status Статус - + Font Шрифт - + Cascade Каскадно - + Tile Замостить - - + + MODBUS Scanner - MODBUS Сканер + Cканер MODBUS - + Long Integer Длинное целое - + Swapped LI Перевернутое ДЦ - + Swapped Long Integer Перевернутое длинное целое - + Unsigned Long Integer Беззнаковое длинное целое - + Swapped Unsigned LI Перевернутое беззнаковое ДЦ - + Swapped Unsigned Long Integer Перевернутое беззнаковое длинное целое - + + + Msg Parser + Анализатор сообщений + + + About Open ModScan... О программе Open ModScan... - + Windows... Окна... - + English - + Русский - + Address scan Сканирование адресов - - - - + + + + All files (*) Все файлы (*) - + %1 was not found %1 не найден - + Failed to open %1 Ошибка открытия файла %1 @@ -1722,47 +1842,338 @@ Valid Slave Responses: %2 ModbusClient - + Invalid Modbus Request Некорректный запрос Modbus - - + + Coil Write Failure Ошибка записи в Coil регистр - - + + Register Write Failure Ошибка записи в регистр - + Mask Write Register Failure Ошибка записи в регистр по маске - + Mask Register Write Failure Ошибка записи в регистр по маске - + Connection error. %1 Ошибка подключения. %1 + + ModbusMessageWidget + + + <span style='color:%1'>*** INVALID MODBUS REQUEST ***</span> + <span style='color:%1'>*** НЕКОРРЕКТНЫЙ MODBUS ЗАПРОС ***</span> + + + + <span style='color:%1'>*** INVALID MODBUS RESPONSE ***</span> + <span style='color:%1'>*** НЕКОРРЕКТНЫЙ MODBUS ОТВЕТ ***</span> + + + + <b>Checksum:</b> %1 + <b>Контрольная сумма:</b> %1 + + + + <b>Checksum:</b> <span style='color:%3'>%1</span> (Expected: %2) + <b>Контрольная сумма:</b> <span style='color:%3'>%1</span> (ожидается: %2) + + + + <b>Type:</b> %1 + <b>Тип:</b> %1 + + + + Request (Tx) + Запрос (Tx) + + + + Response (Rx) + Ответ (Rx) + + + + <b>Timestamp:</b> %1 + <b>Метка времени:</b> %1 + + + + <b>Transaction ID:</b> %1 + <b>Идентификатор транзакции:</b> %1 + + + + <b>Protocol ID:</b> %1 + <b>Идентификатор протокола:</b> %1 + + + + + + + + <b>Length:</b> %1 + <b>Длина:</b> %1 + + + + <b>Device ID:</b> %1 + <b>Устройство:</b> %1 + + + + <b>Error Code:</b> %1 + <b>Код ошибки:</b> %1 + + + + <b>Exception Code:</b> %1 + <b>Код исключения:</b> %1 + + + + <b>Function Code:</b> %1 + <b>Код функции:</b> %1 + + + + + + + <b>Start Address:</b> %1 + <b>Адрес:</b> %1 + + + + + + + + + + + + + + + <b>Byte Count:</b> %1 + <b>Количество байт:</b> %1 + + + + <b>Coil Status:</b> %1 + <b>Статусы coil:</b> %1 + + + + <b>Input Status:</b> %1 + <b>Статусы input:</b> %1 + + + + + + <b>Register Value:</b> %1 + <b>Значения регистров:</b> %1 + + + + <b>Input Registers:</b> %1 + <b>Значения реистров:</b> %1 + + + + + <b>Output Address:</b> %1 + <b>Адрес:</b> %1 + + + + + + <b>Output Value:</b> %1 + <b>Значение:</b> %1 + + + + + <b>Register Address:</b> %1 + <b>Адрес:</b> %1 + + + + <b>Output Data:</b> %1 + <b>Данные:</b> %1 + + + + + <b>Sub-function:</b> %1 + <b>Подфункция:</b> %1 + + + + + + + + + + + <b>Data:</b> %1 + <b>Данные:</b> %1 + + + + + <b>Status:</b> %1 + <b>Статус:</b> %1 + + + + + <b>Event Count:</b> %1 + <b>Количество событий:</b> %1 + + + + <b>Message Count:</b> %1 + <b>Количество сообщений:</b> %1 + + + + <b>Events:</b> %1 + <b>События:</b> %1 + + + + + + + <b>Starting Address:</b> %1 + <b>Начальный адрес:</b> %1 + + + + + <b>Quantity of Outputs:</b> %1 + <b>Количество:</b> %1 + + + + + <b>Quantity of Registers:</b> %1 + <b>Количество регистров:</b> %1 + + + + + <b>Registers Value:</b> %1 + <b>Значения регистров:</b> %1 + + + + <b>Request Data Length:</b> %1 + <b>Длина данных запроса:</b> %1 + + + + <b>Response Data Length:</b> %1 + <b>Длина данных ответа:</b> %1 + + + + + <b>Address:</b> %1 + <b>Адрес:</b> %1 + + + + + <b>And Mask:</b> %1 + <b>Маска «И»:</b> %1 + + + + + <b>Or Mask:</b> %1 + <b>Маска «ИЛИ»:</b> %1 + + + + <b>Read Starting Address:</b> %1 + <b>Адрес чтения регистров:</b> %1 + + + + <b>Quantity to Read:</b> %1 + <b>Количество регистров для чтения:</b> %1 + + + + <b>Write Starting Address:</b> %1 + <b>Адрес записи регистров:</b> %1 + + + + <b>Quantity to Write:</b> %1 + <b>Количество регистров для записи:</b> %1 + + + + <b>Write Byte Count:</b> %1 + <b>Количество байт записи:</b> %1 + + + + <b>Write Registers Value:</b> %1 + <b>Значения регистров записи:</b> %1 + + + + <b>FIFO Point Address:</b> %1 + <b>Адрес точки FIFO:</b> %1 + + + + <b>FIFO Count:</b> %1 + <b>Количество FIFO:</b> %1 + + + + <b>FIFO Value Register:</b> %1 + <b>Значения регистров FIFO:</b> %1 + + OutputWidget - + %1: Enter Description %1: Введите описание - + Data Uninitialized Данные не инициализированы @@ -1788,19 +2199,19 @@ Valid Slave Responses: %2 PdfExporter - + Error. Failed to write PDF file! Ошибка. Не удалось записать PDF файл! - + Device Id: %1 Length: %2 Point Type: [%3] Узел: %1 Количество: %2 Тип регистров: [%3] - + Start Address: %1 Registers on Query: %2 Начальный адрес: %1 @@ -1810,23 +2221,23 @@ Registers on Query: %2 SimulationModeComboBox - - + + Random Случайное - + Toggle Переключение - + Increment Увеличение - + Decrement Уменьшение From b8d884089af23ebd3329d527af8daa32e357e659 Mon Sep 17 00:00:00 2001 From: sanny32 Date: Thu, 12 Oct 2023 09:08:24 +0300 Subject: [PATCH 87/90] Correct ui after translation updated. Some bugs fixed. --- omodscan/controls/modbuslogwidget.cpp | 14 +++++ omodscan/controls/modbuslogwidget.h | 3 + omodscan/controls/modbusmessagewidget.cpp | 14 +++++ omodscan/controls/modbusmessagewidget.h | 3 + omodscan/dialogs/dialogmsgparser.cpp | 21 +++++-- omodscan/dialogs/dialogmsgparser.h | 4 +- omodscan/dialogs/dialogmsgparser.ui | 68 +++++++++++++++++++---- omodscan/dialogs/dialogusermsg.cpp | 27 ++++++--- omodscan/dialogs/dialogusermsg.h | 4 +- omodscan/dialogs/dialogusermsg.ui | 65 ++++++++++++++++++---- omodscan/mainwindow.ui | 2 +- 11 files changed, 189 insertions(+), 36 deletions(-) diff --git a/omodscan/controls/modbuslogwidget.cpp b/omodscan/controls/modbuslogwidget.cpp index 514a7d7..7313d6d 100644 --- a/omodscan/controls/modbuslogwidget.cpp +++ b/omodscan/controls/modbuslogwidget.cpp @@ -1,3 +1,4 @@ +#include #include "htmldelegate.h" #include "modbuslogwidget.h" @@ -131,6 +132,19 @@ ModbusLogWidget::ModbusLogWidget(QWidget* parent) }); } +/// +/// \brief ModbusLogWidget::changeEvent +/// \param event +/// +void ModbusLogWidget::changeEvent(QEvent* event) +{ + if (event->type() == QEvent::LanguageChange) + { + update(); + } + QListView::changeEvent(event); +} + /// /// \brief ModbusLogWidget::clear /// diff --git a/omodscan/controls/modbuslogwidget.h b/omodscan/controls/modbuslogwidget.h index bf541d7..21f3d1f 100644 --- a/omodscan/controls/modbuslogwidget.h +++ b/omodscan/controls/modbuslogwidget.h @@ -65,6 +65,9 @@ class ModbusLogWidget : public QListView bool autoscroll() const; void setAutoscroll(bool on); +protected: + void changeEvent(QEvent* event) override; + private: bool _autoscroll; DataDisplayMode _dataDisplayMode; diff --git a/omodscan/controls/modbusmessagewidget.cpp b/omodscan/controls/modbusmessagewidget.cpp index 612f212..6ae1e9e 100644 --- a/omodscan/controls/modbusmessagewidget.cpp +++ b/omodscan/controls/modbusmessagewidget.cpp @@ -1,3 +1,4 @@ +#include #include "formatutils.h" #include "htmldelegate.h" #include "modbusmessagewidget.h" @@ -19,6 +20,19 @@ ModbusMessageWidget::ModbusMessageWidget(QWidget *parent) setEditTriggers(QAbstractItemView::NoEditTriggers); } +/// +/// \brief ModbusMessageWidget::changeEvent +/// \param event +/// +void ModbusMessageWidget::changeEvent(QEvent* event) +{ + if (event->type() == QEvent::LanguageChange) + { + update(); + } + QListWidget::changeEvent(event); +} + /// /// \brief ModbusMessageWidget::clear /// diff --git a/omodscan/controls/modbusmessagewidget.h b/omodscan/controls/modbusmessagewidget.h index 7a3c1a6..24ee223 100644 --- a/omodscan/controls/modbusmessagewidget.h +++ b/omodscan/controls/modbusmessagewidget.h @@ -29,6 +29,9 @@ class ModbusMessageWidget : public QListWidget void setStatusColor(const QColor& clr); +protected: + void changeEvent(QEvent* event) override; + private: void update(); diff --git a/omodscan/dialogs/dialogmsgparser.cpp b/omodscan/dialogs/dialogmsgparser.cpp index 264b482..0d1e2f7 100644 --- a/omodscan/dialogs/dialogmsgparser.cpp +++ b/omodscan/dialogs/dialogmsgparser.cpp @@ -20,7 +20,6 @@ DialogMsgParser::DialogMsgParser(DataDisplayMode mode, QWidget *parent) Qt::WindowTitleHint); ui->info->setShowTimestamp(false); - ui->buttonBox->button(QDialogButtonBox::Ok)->setText(tr("Parse")); ui->hexView->setCheckState(mode == DataDisplayMode::Hex ? Qt::Checked : Qt::Unchecked); auto dispatcher = QAbstractEventDispatcher::instance(); @@ -36,13 +35,27 @@ DialogMsgParser::~DialogMsgParser() if(_mm) delete _mm; } +/// +/// \brief DialogMsgParser::changeEvent +/// \param event +/// +void DialogMsgParser::changeEvent(QEvent* event) +{ + if (event->type() == QEvent::LanguageChange) + { + ui->retranslateUi(this); + } + + QDialog::changeEvent(event); +} + /// /// \brief DialogMsgParser::on_awake /// void DialogMsgParser::on_awake() { ui->deviceIdIncluded->setVisible(ui->buttonPdu->isChecked()); - ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(!ui->bytesData->isEmpty()); + ui->pushButtonParse->setEnabled(!ui->bytesData->isEmpty()); } /// @@ -75,9 +88,9 @@ void DialogMsgParser::on_bytesData_valueChanged(const QByteArray& value) } /// -/// \brief DialogMsgParser::accept +/// \brief DialogMsgParser::on_pushButtonParse_clicked /// -void DialogMsgParser::accept() +void DialogMsgParser::on_pushButtonParse_clicked() { auto data = ui->bytesData->value(); if(data.isEmpty()) return; diff --git a/omodscan/dialogs/dialogmsgparser.h b/omodscan/dialogs/dialogmsgparser.h index cce4d9e..54b22bc 100644 --- a/omodscan/dialogs/dialogmsgparser.h +++ b/omodscan/dialogs/dialogmsgparser.h @@ -20,12 +20,14 @@ class DialogMsgParser : public QDialog explicit DialogMsgParser(DataDisplayMode mode, QWidget *parent = nullptr); ~DialogMsgParser(); - void accept() override; +protected: + void changeEvent(QEvent* event) override; private slots: void on_awake(); void on_hexView_toggled(bool); void on_bytesData_valueChanged(const QByteArray& value); + void on_pushButtonParse_clicked(); private: Ui::DialogMsgParser *ui; diff --git a/omodscan/dialogs/dialogmsgparser.ui b/omodscan/dialogs/dialogmsgparser.ui index a128bb0..fd04c62 100644 --- a/omodscan/dialogs/dialogmsgparser.ui +++ b/omodscan/dialogs/dialogmsgparser.ui @@ -188,17 +188,63 @@
- - - Qt::Horizontal - - - QDialogButtonBox::Close|QDialogButtonBox::Ok - - - true - - + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Parse + + + false + + + + + + + + 0 + 0 + + + + Qt::Horizontal + + + QDialogButtonBox::Close + + + false + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + diff --git a/omodscan/dialogs/dialogusermsg.cpp b/omodscan/dialogs/dialogusermsg.cpp index c43c77f..8ad38a5 100644 --- a/omodscan/dialogs/dialogusermsg.cpp +++ b/omodscan/dialogs/dialogusermsg.cpp @@ -43,9 +43,7 @@ DialogUserMsg::DialogUserMsg(quint8 slaveAddress, QModbusPdu::FunctionCode func, break; } - ui->buttonBox->button(QDialogButtonBox::Ok)->setText(tr("Send")); ui->sendData->setFocus(); - connect(&_modbusClient, &ModbusClient::modbusReply, this, &DialogUserMsg::on_modbusReply); } @@ -59,11 +57,26 @@ DialogUserMsg::~DialogUserMsg() } /// -/// \brief DialogUserMsg::accept +/// \brief DialogUserMsg::changeEvent +/// \param event +/// +void DialogUserMsg::changeEvent(QEvent* event) +{ + if (event->type() == QEvent::LanguageChange) + { + ui->retranslateUi(this); + } + + QDialog::changeEvent(event); +} + +/// +/// \brief DialogUserMsg::on_pushButtonSend_clicked /// -void DialogUserMsg::accept() +void DialogUserMsg::on_pushButtonSend_clicked() { ui->responseBuffer->clear(); + ui->responseInfo->clear(); if(_modbusClient.state() != QModbusDevice::ConnectedState) { @@ -71,7 +84,7 @@ void DialogUserMsg::accept() return; } - ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false); + ui->pushButtonSend->setEnabled(false); QModbusRequest request; request.setFunctionCode(ui->comboBoxFunction->currentFunctionCode()); @@ -80,7 +93,7 @@ void DialogUserMsg::accept() _modbusClient.sendRawRequest(request, ui->lineEditSlaveAddress->value(), 0); const auto timeout = _modbusClient.timeout() * _modbusClient.numberOfRetries(); - QTimer::singleShot(timeout, this, [&] { ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(true); }); + QTimer::singleShot(timeout, this, [&] { ui->pushButtonSend->setEnabled(true); }); } /// @@ -109,7 +122,7 @@ void DialogUserMsg::on_modbusReply(QModbusReply* reply) ui->responseBuffer->setValue(*_mm); ui->responseInfo->setModbusMessage(_mm); - ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(true); + ui->pushButtonSend->setEnabled(true); } /// diff --git a/omodscan/dialogs/dialogusermsg.h b/omodscan/dialogs/dialogusermsg.h index 30e2e3c..84b460c 100644 --- a/omodscan/dialogs/dialogusermsg.h +++ b/omodscan/dialogs/dialogusermsg.h @@ -19,12 +19,14 @@ class DialogUserMsg : public QDialog explicit DialogUserMsg(quint8 slaveAddres, QModbusPdu::FunctionCode func, DataDisplayMode mode, ModbusClient& client, QWidget *parent = nullptr); ~DialogUserMsg(); - void accept() override; +protected: + void changeEvent(QEvent* event) override; private slots: void on_modbusReply(QModbusReply* reply); void on_radioButtonHex_clicked(bool checked); void on_radioButtonDecimal_clicked(bool checked); + void on_pushButtonSend_clicked(); private: Ui::DialogUserMsg *ui; diff --git a/omodscan/dialogs/dialogusermsg.ui b/omodscan/dialogs/dialogusermsg.ui index 42931f6..0701fd5 100644 --- a/omodscan/dialogs/dialogusermsg.ui +++ b/omodscan/dialogs/dialogusermsg.ui @@ -222,17 +222,60 @@ - - - Qt::Horizontal - - - QDialogButtonBox::Cancel|QDialogButtonBox::Ok - - - true - - + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Send + + + false + + + + + + + + 0 + 0 + + + + Qt::Horizontal + + + QDialogButtonBox::Close + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + diff --git a/omodscan/mainwindow.ui b/omodscan/mainwindow.ui index 49e847a..27c73e1 100644 --- a/omodscan/mainwindow.ui +++ b/omodscan/mainwindow.ui @@ -764,7 +764,7 @@ Msg Parser - F9 + F9 From f79e4451b5e3dc735f5b70227a3e497d5c32b6b4 Mon Sep 17 00:00:00 2001 From: sanny32 Date: Thu, 12 Oct 2023 10:59:48 +0300 Subject: [PATCH 88/90] Update translation --- omodscan/translations/omodscan_ru.qm | Bin 38780 -> 38828 bytes omodscan/translations/omodscan_ru.ts | 4 ++-- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/omodscan/translations/omodscan_ru.qm b/omodscan/translations/omodscan_ru.qm index 02745295653abea491e52e0f73a76d8d61a51377..defbe2eb470fd553df9295a61c0a007fb985c2a4 100644 GIT binary patch delta 2743 zcmZuzX;>6j7Clv6)zw|Sg($K_1vH9r2U)e*BSC}~L`7LdL{t_L2%@6cD59bmz>**+ zNL+BiDDF$5X^s1aOVrVP8Xd#L1yD08lZZN(ujc2_-^Z!<-hHp`J@?%Es$)01YY$u2 z*IWwllYvojfUpN}8wR)+0KUfo(|O>_|6xKOAZjTvu2sgOjr4pDNDKkSZvh4!Av{ax z^Z{2w=XgEfo2JRZ2*+2d`xZC4^$sXWZh7!I7-z|+c zmV$R9gK;NiEXpWvvT=C`e%%=$sSSM9B0zf!{Dv=qk&WORrT{vcZ=_8#&ET8JyHs1r zhVe6RL8wOsFew{hRZ{_PYlQ7|0&>lWnso{o?t}@R#efo+u#Cnd#$ZA**?W2-IwcPn zat#wl&Y{J8OgwxPFs{L*OBP_-A;ioeJC}UK9A5(@oIzaSLE@kcd8y>h%22G!rv1__ z#?CC^@o)+=vJTJxJ_#&p!iV)KfMy}XSW_fR=P_FL6|nGI#%JCGKtEZ=kZKu2=Q3e? zBZy-Q6Yg3Cs3Mt3a0PIMnPW8#@DZ5&Qift`X6oL22Q1jg9NDvj&K<(sb~pg^3LMO| zw*C%G^kn|({Q~IM!hGoYn#d?;wLKOCndhZa*1`NY8}JK-I*VaVbt2$8icL1Y1Dp=C zvn``Y7OiaN%xH4Yk(CBy0rTFodo#)a!)o@><9$F%EPMDExlyo)wFLeN#8$JGCxmhS z?CEFE08t^MT^AW6MzBp`cEF5K_R&|H0dv1{_R%TgVU9QZ?A|6|^g$WJ-m$M$?m(Yk z*uOF+0k$b@$8Cyh>Tv}M$$r*!MNcEeov~Ko>`_da->UGactm`4SB(C_9|*2egm1n` zdb3kRFPsnf?^eWIqyXk@SHw5p06ff!tZP;ktM`ydlv}v^uy(?m+|i58T`3_Z?u4iZzE~+^j7jq2Y|P(q=Ym~; zJbUi4CKCvJ#@#c%q7Q21kKaxcy>`kN z@`sF}=VS~!#7`{SMGAoQk=$+Pb1TVusKDo4F93>N_!Xn$fffGzngzsK&QE;BMT%Ms z=4-aSqH@ULzf+OD@dCed)z3h3G=J~`xwE2>KN{IaX?Ec)z3YH32{Jl2^Ol)p?{kyC z@Gnwtb}E0_bt~X?hrg0%qLQoNt<(Yh2d7#pXO*;vw_(mo=Xhu4hV+7-H%fxi!Ms{o ztf>YD?^UjS6-gAfC@asAFGB;A>kD&e-wNfaom7fpamw>GQ|Mh$%3HQAfb}ZnZyWCr zWwpwu)q%kD$I6z(59He+Wy_il^8LD?n0*%*`(EI^NYj&(1f5Gc)yitYXVPG5voi(1 zPP9+V5yJ0Yr5E=W#`d2|(r6IIkIbMx(=Pp_v>D|tWLzXAPv0Qq-=>oK+9VWoIZfTU zi%`1vI#oI&l*Oze%It)1t0_aCn}zyqL`Cr>p`qk4RmytddpojQaanQ@Y`oiq){m4| z_XRQr-BI!FMA*<;ipuleI(a}H>!llB@~38G+S`Cb5%9uQ1|hE zq&mp#20l+xo&T}(o$1mZI(wg*&s{`GTB_z7JjtU8YWrWKfPhl<@I_fb)?oFBel9@% zd$sR~p>zk#QwQGgr`k-AJ_-&lM)m2)XcEpz_1))0SGUFLr+H<-Cxz-~eP~x!h5E(l za$tU;`h6lvAZnd7MrFg?l4htJ%ofq=^*&(WZW*Vfh;H}j2K(ZM=v_wK`D#St+elJx zqnP;4joMMHm^_-AV9Y0C>Rp=8uMyM!T?=%tlF{KuF{^}9IO@8XTOB}|Fp8^w?o7QT zmZWzDmj6dA$)^3w8^yB2#I<=@wphc{!(xTFtEPaiOS9OROa%2FAU0mU1$-4N9=U1{ z^c^CjDMdV{Fakl<;)OaQF#d^nFNChxqMPFLU^NhZKz!Rq_SP>o>iNl_KN({OX_75e z56)B91ont4Do{f;$0L*y_`+DQ}jy9`bGYs%M@&o%i$#8ys}v{CJB-k~XZME-|F z%NXh+W7wyfW1Fl@-#O?0NSlA>iSmb9sZcL1{mZRUW-q?)c$rRcz2vl_@!7@c^E$@T2iFGaqo!MG!2o?-Jx$yA>FdvxlghT} zTd!mjyL0p}yF5Z?vsPwzX61vyI)Ppq>~65?>YiNr|A#A39E6+;TXY|_tR$Joc?#4NBzMLE9&iQj5oEH}eM{YRH_;7(V wWKOAI>dYNMY zJ{lO)7Z9oe*FnJGJiu!m5ONk6^?!_h1B9&r!cQugpH9b3K&&+|@f)DuQNkaAfH&X@ z={Z9Vg4?%^Vg@OguLpOr0dV>N?lK2Vs|I(aC(tKq9k?6eK(rcM+d#q}!FNreg)!h= zDImO9!F;dc%T~@c;5VHC;u^r0EdiwK;J+RP_~n7GnhxmO!Pn5D#Bty+Q+7$e%T|oH zISXUmN`MGo1eMJI+#e%opFNO04q>xT0Uj?gX-EN}1}3ef^I;}TDxmlw0wyQr00XXI zir+lC8H_3Q#{kb6h`7)Q#IHo;EQ)i^MdZm1KuigyEw3Xkrz0nsvRPw`O>=0ye4Vi| z$Kl~nDl;?#PyhQpuw*+rwj=?%#SCLfm8=M0B=#k+cqTJ^!OwspTET#11;>tNf@;ST z$3;xAOBtXEWg_4LpqZIx5l=bYWOCOtR8t*O{$>ZTD4jW4y%$*ik-1^|7U<#A!908R z2$&);e>yw|dbcqhcCV@USXTOcDUh*AUeB7$=UJa?RBCDq8&WO;E@RjP&-Z|RJ)7P* zhGcP)%}AU~>2+sir%Yf$Gh3Th1Q^$`M;;y`!kyUqWy?MoT>+ST7qbse5fAgUZ0nt!Kw!RtK^NH9n!!NNYwVwC z5rB0P`{4%FHDjF$%PD@go663U>Q0MSIl2`9$@5fhB@akGZK}ZUMgaavs^E(Aq&FMY zV6{v^ms0NK^m3Yvquk4z-GQ;U_`V@~0A`kg zeN%b&sf&T3eR$9LkBP@$c<-v7bRN(9w>yxQJ@^3kMmjI&18qqreNxi+iF@cmk9`UT z)GIi)RKcK?{FI{oG(B@ZZI_|<_?!0Jx?hDF3$)_T6=JXJ0F z^ILbnq;VL<@6b@ZXBoe5?GHeLBVYG3rL#JWKNi|f=`nnxLpjhnMnT8Nd}AWT53k_Q z{YL7YGnBvRvWrH0H{YBSLL*ngTWBr#4*P9X!Y#R)w_-NRO}rzsQ+`gz>9U|UnWNMN zy3IiUTJ={iLy5u@>e434WuT9G%knI;fhp=!`)Cw{`l`=volfs^P+zxh11#67f7yPM zOejtLWV0_Y^RT)twu5pzqHf#pfpXs=sM2o(6Pg9yoirUiNYFbM)2u`Z!z22W%_a)o zpU^gTln{LT5?8Gc zaG-)CcWd}}MA*RV8rScR1D|O${(DFd!5cIohe)n5XEZUP%cuyWoGv)pu$rnYavzUc zO&xO(_-CBv?1@kB^pvaV*~_$i_7ZARxR$RPLQU+YwY?h#_{3<3F3BWo>Cg`A?F{5L zYrTdIq&;AP*7xcN^0EQ)N5SMQX-|hvChI8H-hN7SbzQ1`l2Zh9TCQ#FNvkpww9f;J zN%>*gzhX%OVTtlMjTN&?o~1FFi$sgphk(8Z6`bxNy56B3?2D_SM-g#1{I2NvHk8y` zBgVdWB|CBw69UNuBkqgIx9NKBY%%54HlSOXf~FHi@eq%zJb{tP;<<7nFzTpyCxEup{0i}@zZRIhLVVj!@s=-i+Jy=x7=cP-1P5p{_t;-!rY-Ksf+qI77g}TBAlz)Ju zf@2v41Ao;W-)TXbD$_Oo%93QK=-R#tr+V{r&l*T$(aRC_r#$QGJ z9hI!6HqhASNls(WP#U7t&+zuIY=?x zf)q5RNU@IetT;yn3*w~Y{(H%}Z%P?X56PJy$)%!+879|@c0C5akxo{T>)LYCsra41 z%8SyatJyRvjnb{M7TPXb<#%E)^ZdK|K_3`kepkJR^_KuQUhgxAZb$XgPdz&rn4YJP zUHmP5rMT&n_I4)?ozrJoQs0-h>q~v8&P9^G;-o80!&3dbOR>QC?fUltaX|Op`i@6* zKf~L=9XU+xd~UGr+#j&x6twpSqHWib~vJB6f z=a85C8D4aL0HV&Qp7W_ImyDJ%^iqG`Xv@(#^Vm4%_(Ixp`Y7mSGR}BLvpjyZF*TRO z<37TeeR&sc?h}nG1!5=tC)q4ndAS)YO6-Y)R^xtE7A4W5;EGD){t!B!_HW~96LB&> z+jy@u8d!GK*gigqzAWnKZ_P%TN$hd>tyJjB^pJmB)I+ZKakcEiIdDFlFE@ho;ynI$ N Device Id included - Устройство + Содержит номер устройства Checksum included - Контрольная сумма + Содержит контрольную сумму From e0e9ab3d806ffbaccda201042bf330eaefdd4853 Mon Sep 17 00:00:00 2001 From: Alexandr Ananev Date: Thu, 12 Oct 2023 12:54:57 +0300 Subject: [PATCH 89/90] Update README.md --- README.md | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 9ba8aa2..76d207f 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,10 @@ # Open ModScan Open ModScan is a free implimentation of modbus master (client) utility for modbus-tcp and modbus-rtu protocols. -![изображение](https://github.com/sanny32/OpenModScan/assets/13627951/aa912ece-4b76-44b4-9523-5b0b0156a64b) +![image](https://github.com/sanny32/OpenModScan/assets/13627951/aa912ece-4b76-44b4-9523-5b0b0156a64b) -![изображение](https://github.com/sanny32/OpenModScan/assets/13627951/77bee5d8-09a8-4845-8d64-02b7bf3cf592) - +![image](https://github.com/sanny32/OpenModScan/assets/13627951/77bee5d8-09a8-4845-8d64-02b7bf3cf592) ## Features @@ -26,18 +25,28 @@ Registers 0x06 - Write Single Register 0x10 - Write Multiple Registers 0x16 - Mask Write Register + +Modbus Logging + +![image](https://github.com/sanny32/OpenModScan/assets/13627951/de14b977-08ba-460c-814c-7affd0d88f91) + ## Extended Featues - Modbus Address Scan +- Modbus Address Scan - ![image](https://user-images.githubusercontent.com/13627951/226310086-4160c8c7-503a-48c0-bdf8-f5bb970592d3.png) + ![image](https://github.com/sanny32/OpenModScan/assets/13627951/8989fbde-09f1-435c-a9a7-31e27a0ec576) - Modbus Scanner (supports both Modbus RTU and Modbus TCP scanning) - +- Modbus Scanner (supports both Modbus RTU and Modbus TCP scanning) ![image](https://github.com/sanny32/OpenModScan/assets/13627951/056de3b1-026b-498b-914c-4d1e565067bb) +- Modbus Message Parser + + ![image](https://github.com/sanny32/OpenModScan/assets/13627951/86a82340-015e-4ee9-a483-b5ab83527cc1) +- Modbus User Message + + ![image](https://github.com/sanny32/OpenModScan/assets/13627951/5ee959a2-9c5c-4ffe-8056-d6205e3b5aa3) ## Building Now building is available with Qt/qmake (version 5.15 and above) or Qt Creator. Supports both OS Microsoft Windows and Linux. From 6add0bf1506fc250da4651e64e2c4d2cdd62ceee Mon Sep 17 00:00:00 2001 From: Alexandr Ananev Date: Thu, 12 Oct 2023 13:13:28 +0300 Subject: [PATCH 90/90] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 76d207f..8e0f1f8 100644 --- a/README.md +++ b/README.md @@ -38,7 +38,7 @@ Modbus Logging - Modbus Scanner (supports both Modbus RTU and Modbus TCP scanning) - ![image](https://github.com/sanny32/OpenModScan/assets/13627951/056de3b1-026b-498b-914c-4d1e565067bb) + ![image](https://github.com/sanny32/OpenModScan/assets/13627951/768a9c69-0201-4c1e-bad5-4fa9b24d9553) - Modbus Message Parser