diff options
author | Alex Blasche <alexander.blasche@qt.io> | 2018-02-27 16:49:48 +0100 |
---|---|---|
committer | Alex Blasche <alexander.blasche@qt.io> | 2018-10-24 06:01:31 +0000 |
commit | fcf05e2399a2d94af1c6a907221a95e3ab96ed1d (patch) | |
tree | 81c407b179223db2491b6f941cd86ed010cf2acc | |
parent | 682c5ca041483b7d3e8994e7fac5bcab6327e5c2 (diff) |
Fix RTU Master ignoring responses due to being in Send state
The fix for QTBUG-62299 limits the processing of serial responses
in RTU serial master to cases when the state machine is in receive mode
only. So far the Receive state was triggered by the sendTimer. However
modern kernels accept serial packages faster then the sendTimer can fire.
This patches addresses the problem by setting the Receive state even before
sendTimer fires. If the bytesWritten() callback detects that the entire
PDU/ADU was written it stops sendTimer and immediately progresses the
state machine to the Receive state.
Fixes: QTBUG-69188
Change-Id: I1657973ef99f1b3e4008e887029b30890d825d59
Reviewed-by: Karsten Heimrich <karsten.heimrich@qt.io>
-rw-r--r-- | src/serialbus/qmodbusrtuserialmaster_p.h | 13 |
1 files changed, 11 insertions, 2 deletions
diff --git a/src/serialbus/qmodbusrtuserialmaster_p.h b/src/serialbus/qmodbusrtuserialmaster_p.h index 9a75de5..104c365 100644 --- a/src/serialbus/qmodbusrtuserialmaster_p.h +++ b/src/serialbus/qmodbusrtuserialmaster_p.h @@ -151,8 +151,10 @@ public: return; } - if (m_state != State::Receive) + if (m_state != State::Receive) { + qCDebug(QT_MODBUS) << "(RTU server) Ignoring response due to non receive state"; return; + } m_sendTimer.stop(); m_responseTimer.stop(); @@ -215,6 +217,13 @@ public: QObject::connect(m_serialPort, &QSerialPort::bytesWritten, q, [this](qint64 bytes) { m_current.bytesWritten += bytes; + if (m_state == Send && (m_current.bytesWritten == m_current.adu.size()) && !m_current.reply.isNull()) { + // the if conditions above are copied from processQueue() + qCDebug(QT_MODBUS) << "(RTU client) Send successful (quick):" << m_current.requestPdu; + m_state = Receive; + m_sendTimer.stop(); + m_responseTimer.start(m_responseTimeoutDuration); + } }); QObject::connect(m_serialPort, &QSerialPort::aboutToClose, q, [this]() { @@ -321,7 +330,7 @@ public: break; case Send: - // send timeout will always happen + // send timeout will always happen unless cancelled by very quick bytesWritten if (m_current.reply.isNull()) { scheduleNextRequest(); } else if (m_current.bytesWritten < m_current.adu.size()) { |