From 19d515266cf416f2fd003454d52331ad40e1ac07 Mon Sep 17 00:00:00 2001 From: Karsten Heimrich Date: Mon, 20 Apr 2020 14:19:11 +0200 Subject: Report intermediate errors while in a Modbus send/receive cycle Task-number: QTBUG-79312 Change-Id: Iec1f9a0427bd04ebb8ceb4c66ece96e443092a6e Reviewed-by: Alex Blasche --- src/serialbus/qmodbusdevice.cpp | 21 ++++++++++++++++++ src/serialbus/qmodbusdevice.h | 8 +++++++ src/serialbus/qmodbusreply.cpp | 37 +++++++++++++++++++++++++++++++- src/serialbus/qmodbusreply.h | 5 +++++ src/serialbus/qmodbusrtuserialmaster_p.h | 4 +++- 5 files changed, 73 insertions(+), 2 deletions(-) diff --git a/src/serialbus/qmodbusdevice.cpp b/src/serialbus/qmodbusdevice.cpp index ab8e126..7c81ebf 100644 --- a/src/serialbus/qmodbusdevice.cpp +++ b/src/serialbus/qmodbusdevice.cpp @@ -216,6 +216,27 @@ void QModbusDevice::setConnectionParameter(int parameter, const QVariant &value) \value ClosingState The device is being closed. */ +/*! + \since 6.0 + \enum QModbusDevice::IntermediateError + + This enum describes possible errors that can happen during a full send and + receive cycle for a Modbus reply. + + \value ResponseCrcError A Modbus response with a wrong CRC was received. + \value ResponseRequestMismatch A Modbus response was received but did not + match the open request, probably due to the + PDU's function code not matching. + + If any of the above intermediate errors occurred, the frame is likely + resent until the maximum number of retries has been reached. + + The list of intermediate errors can be inspected from the \l QModbusReply + intermediate errors function. + + \sa QModbusClient::numberOfRetries(), QModbusReply::intermediateErrors() +*/ + /*! \fn QModbusDevice::errorOccurred(QModbusDevice::Error error) diff --git a/src/serialbus/qmodbusdevice.h b/src/serialbus/qmodbusdevice.h index 0e6dad7..0a51a84 100644 --- a/src/serialbus/qmodbusdevice.h +++ b/src/serialbus/qmodbusdevice.h @@ -86,6 +86,13 @@ public: }; Q_ENUM(ConnectionParameter) + enum IntermediateError + { + ResponseCrcError, + ResponseRequestMismatch + }; + Q_ENUM(IntermediateError) + explicit QModbusDevice(QObject *parent = nullptr); ~QModbusDevice(); @@ -118,6 +125,7 @@ protected: Q_DECLARE_TYPEINFO(QModbusDevice::Error, Q_PRIMITIVE_TYPE); Q_DECLARE_TYPEINFO(QModbusDevice::State, Q_PRIMITIVE_TYPE); Q_DECLARE_TYPEINFO(QModbusDevice::ConnectionParameter, Q_PRIMITIVE_TYPE); +Q_DECLARE_TYPEINFO(QModbusDevice::IntermediateError, Q_PRIMITIVE_TYPE); QT_END_NAMESPACE diff --git a/src/serialbus/qmodbusreply.cpp b/src/serialbus/qmodbusreply.cpp index caa2dd9..e5561c2 100644 --- a/src/serialbus/qmodbusreply.cpp +++ b/src/serialbus/qmodbusreply.cpp @@ -53,6 +53,7 @@ public: QString m_errorText; QModbusResponse m_response; QModbusReply::ReplyType m_type; + QVector m_intermediateErrors; }; /*! @@ -239,7 +240,6 @@ QString QModbusReply::errorString() const return d->m_errorText; } - /*! Returns the type of the reply. @@ -278,6 +278,41 @@ void QModbusReply::setRawResult(const QModbusResponse &response) d->m_response = response; } +/*! + \since 6.0 + \fn void intermediateErrorOccurred(QModbusDevice::IntermediateError error) + + This signal is emitted when an error has been detected in the processing of + this reply. The error will be described by the error code \a error. +*/ + +/*! + \since 6.0 + + Returns the list of intermediate errors that might have happened during + the send-receive cycle of a Modbus request until the QModbusReply reports + to be finished. +*/ +QVector QModbusReply::intermediateErrors() const +{ + Q_D(const QModbusReply); + return d->m_intermediateErrors; +} + +/*! + \internal + \since 6.0 + + Adds an intermediate error to the list of intermediate errors. + This will also cause the \l intermediateErrorOccurred() signal to be emitted. +*/ +void QModbusReply::addIntermediateError(QModbusDevice::IntermediateError error) +{ + Q_D(QModbusReply); + d->m_intermediateErrors.append(error); + emit intermediateErrorOccurred(error); +} + QT_END_NAMESPACE #include "moc_qmodbusreply.cpp" diff --git a/src/serialbus/qmodbusreply.h b/src/serialbus/qmodbusreply.h index ffefc89..7381912 100644 --- a/src/serialbus/qmodbusreply.h +++ b/src/serialbus/qmodbusreply.h @@ -37,6 +37,7 @@ #ifndef QMODBUSREPLY_H #define QMODBUSREPLY_H +#include #include #include #include @@ -77,9 +78,13 @@ public: void setFinished(bool isFinished); void setError(QModbusDevice::Error error, const QString &errorText); + QVector intermediateErrors() const; + void addIntermediateError(QModbusDevice::IntermediateError error); + Q_SIGNALS: void finished(); void errorOccurred(QModbusDevice::Error error); + void intermediateErrorOccurred(QModbusDevice::IntermediateError error); }; Q_DECLARE_TYPEINFO(QModbusReply::ReplyType, Q_PRIMITIVE_TYPE); diff --git a/src/serialbus/qmodbusrtuserialmaster_p.h b/src/serialbus/qmodbusrtuserialmaster_p.h index d206eec..4c75951 100644 --- a/src/serialbus/qmodbusrtuserialmaster_p.h +++ b/src/serialbus/qmodbusrtuserialmaster_p.h @@ -98,7 +98,7 @@ private: class QModbusRtuSerialMasterPrivate : public QModbusClientPrivate { Q_DECLARE_PUBLIC(QModbusRtuSerialMaster) - enum State + enum State { Idle, WaitingForReplay, @@ -165,6 +165,7 @@ public: qCWarning(QT_MODBUS) << "(RTU client) Discarding response with wrong CRC, received:" << adu.checksum() << ", calculated CRC:" << QModbusSerialAdu::calculateCRC(adu.data(), adu.size()); + m_queue.first().reply->addIntermediateError(QModbusClient::ResponseCrcError); return; } @@ -172,6 +173,7 @@ public: if (!canMatchRequestAndResponse(response, adu.serverAddress())) { qCWarning(QT_MODBUS) << "(RTU client) Cannot match response with open request, " "ignoring"; + m_queue.first().reply->addIntermediateError(QModbusClient::ResponseRequestMismatch); return; } -- cgit v1.2.3