Uploaded image for project: 'Qt'
  1. Qt
  2. QTBUG-98644

Support raw requests on standard function codes

    XMLWordPrintable

Details

    • Bug
    • Resolution: Unresolved
    • P2: Important
    • None
    • 6.2.1
    • SerialBus: MOD Bus
    • None

    Description

      In the project I am working, we have recently switched from using libmodbus to QtSerialbus for Modbus communication with both proprietary devices and off-the-shelf devices. The proprietary one is implemented in such a way that one needs to read the Exception Status (function code 7) periodically to get information that other registers have been updated.

      The current version of QtSerialbus only supports reading from and writing to a limited subset of register types. Therefore I figured we could use a raw request for reading function code 7. However, this always results in a QModbusDevice::UnknownError.

      From qtserialbus/src/serialbus/qmodbusrtuserialclient_p.h:

      class QModbusRtuSerialClientPrivate : public QModbusClientPrivate
      {
          ...
      public:
          void onReadyRead()
          {
              ...
              processQueueElement(response, m_queue.dequeue());
              ...
          }
      }

      From qtserialbus/src/serialbus/qmodbusclient.cpp:

      void QModbusClientPrivate::processQueueElement(const QModbusResponse &pdu,
                                                     const QueueElement &element)
      {
          ....
          if (element.reply->type() == QModbusReply::Broadcast) {
              element.reply->setFinished(true);
              return;
          }
      
          QModbusDataUnit unit = element.unit;
          if (!processResponse(pdu, &unit)) {
              element.reply->setError(QModbusDevice::UnknownError,
                  QModbusClient::tr("An invalid response has been received."));
              return;
          }
      
          element.reply->setResult(unit);
          element.reply->setFinished(true);
      

      And, finally, further down in qmodbusclient.cpp:

      bool QModbusClientPrivate::processResponse(const QModbusResponse &response, QModbusDataUnit *data)
      {
          switch (response.functionCode()) {
          case QModbusRequest::ReadCoils:
              return processReadCoilsResponse(response, data);
          case QModbusRequest::ReadDiscreteInputs:
              return processReadDiscreteInputsResponse(response, data);
          case QModbusRequest::ReadHoldingRegisters:
              return processReadHoldingRegistersResponse(response, data);
          case QModbusRequest::ReadInputRegisters:
              return processReadInputRegistersResponse(response, data);
          case QModbusRequest::WriteSingleCoil:
              return processWriteSingleCoilResponse(response, data);
          case QModbusRequest::WriteSingleRegister:
              return processWriteSingleRegisterResponse(response, data);
          case QModbusRequest::ReadExceptionStatus:
          case QModbusRequest::Diagnostics:
          case QModbusRequest::GetCommEventCounter:
          case QModbusRequest::GetCommEventLog:
              return false;   // Return early, it's not a private response
          ...
      }
      

      Basically, a response to e.g. a QModbusRequest::ReadExceptionStatus is always considered "non-private", and, since processResponse() then returns false, processQueueElement() will set the error UnknownError and the reply can thus not be used.

      I am attaching a patch with my suggested change.

      Attachments

        No reviews matched the request. Check your Options in the drop-down menu of this sections header.

        Activity

          People

            heimrich Karsten Heimrich
            jharden Jonas Hården
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

            Dates

              Created:
              Updated:

              Gerrit Reviews

                There are no open Gerrit changes