Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. QSerialPort readAll() does not work with 5.14.0 anymore
Forum Updated to NodeBB v4.3 + New Features

QSerialPort readAll() does not work with 5.14.0 anymore

Scheduled Pinned Locked Moved Solved General and Desktop
33 Posts 4 Posters 6.3k Views 2 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • K Offline
    K Offline
    kuzulis
    Qt Champions 2020
    wrote on last edited by kuzulis
    #3

    @rasc said in QSerialPort readAll() does not work with 5.14.0 anymore:

    HardwareControl

    Are you sure in this flow control? Do you use and the RTS/CTS line pinouts?

    You can also check on the received data after the waitForBytesWritten()... Also, make sure that the waitForReadyRead() triggered too.

    1 Reply Last reply
    0
    • R Offline
      R Offline
      rasc
      wrote on last edited by
      #4

      @JonB I now tested the QSerialPort Terminal example https://doc.qt.io/qt-5/qtserialport-terminal-example.html which uses async communication with signal/slots and this does indeed work with 5.14 onwards as well. I guess I could make it work using signal/slots, but I still wonder why it doesn't work anymore when using the blocking approach.

      @kuzulis I am not absolutely sure about the settings, since I determined them by try and error (and by recording the device communication when using the manufacturer software). However, communication with the microscope only worked when using HardwareControl, and it did work with 5.13.2. So I think these settings should be ok.
      I will check whether waitforReadyRead() triggered.

      JonBJ K 2 Replies Last reply
      0
      • R rasc

        @JonB I now tested the QSerialPort Terminal example https://doc.qt.io/qt-5/qtserialport-terminal-example.html which uses async communication with signal/slots and this does indeed work with 5.14 onwards as well. I guess I could make it work using signal/slots, but I still wonder why it doesn't work anymore when using the blocking approach.

        @kuzulis I am not absolutely sure about the settings, since I determined them by try and error (and by recording the device communication when using the manufacturer software). However, communication with the microscope only worked when using HardwareControl, and it did work with 5.13.2. So I think these settings should be ok.
        I will check whether waitforReadyRead() triggered.

        JonBJ Offline
        JonBJ Offline
        JonB
        wrote on last edited by JonB
        #5

        @rasc
        So if it works with signals/slots I assume there cannot be a pin control etc. issue.

        The waitFor...()s are a bit "dodgy". It looks like you are reporting a change in their behaviour. If you want to stick with them you probably need to try to see where exactly it does not behave as expected in those blocking calls. For example, I have no idea whether upping the timeouts (e.g. your while (waitForReadyRead(50))) would improve the situation.

        R 1 Reply Last reply
        0
        • R rasc

          @JonB I now tested the QSerialPort Terminal example https://doc.qt.io/qt-5/qtserialport-terminal-example.html which uses async communication with signal/slots and this does indeed work with 5.14 onwards as well. I guess I could make it work using signal/slots, but I still wonder why it doesn't work anymore when using the blocking approach.

          @kuzulis I am not absolutely sure about the settings, since I determined them by try and error (and by recording the device communication when using the manufacturer software). However, communication with the microscope only worked when using HardwareControl, and it did work with 5.13.2. So I think these settings should be ok.
          I will check whether waitforReadyRead() triggered.

          K Offline
          K Offline
          kuzulis
          Qt Champions 2020
          wrote on last edited by kuzulis
          #6

          @rasc said in QSerialPort readAll() does not work with 5.14.0 anymore:

          HardwareControl

          If you use the TX/RX pins only, then the HardwareControl do not need (it even may cause a problems), because in this mode the serial port driver waits for the RTS/CTS pins handshake.

          1 Reply Last reply
          1
          • JonBJ JonB

            @rasc
            So if it works with signals/slots I assume there cannot be a pin control etc. issue.

            The waitFor...()s are a bit "dodgy". It looks like you are reporting a change in their behaviour. If you want to stick with them you probably need to try to see where exactly it does not behave as expected in those blocking calls. For example, I have no idea whether upping the timeouts (e.g. your while (waitForReadyRead(50))) would improve the situation.

            R Offline
            R Offline
            rasc
            wrote on last edited by
            #7

            @JonB I am fine with switching to the signals/slots approach. I only used the blocking approach, because it was a bit faster/simpler to implement in the first place. I will anyway try to debug this a bit more, since I really wonder what broke here. But I will switch to async if I cannot fix the blocking approach. Increasing the timeout did not help.

            @kuzulis I don't think the HardwareControl is the issue here, since the handshake works (I think). I can send data to the device and it reacts accordingly. Only receiving data does not work.

            1 Reply Last reply
            0
            • K Offline
              K Offline
              kuzulis
              Qt Champions 2020
              wrote on last edited by kuzulis
              #8

              I just checked the QSP with the Qt 5.15.0 (there are no changes between 5.14.0 and 5.15.x) using the virtual com0com serial ports and the following simple example:

              #include <QCoreApplication>
              #include <QSerialPort>
              #include <QDebug>
              
              int main(int argc, char *argv[])
              {
                  QCoreApplication a(argc, argv);
                  QSerialPort sp("COM3");
                  qDebug() << "OPEN:" << sp.open(QIODevice::ReadWrite);
                  for (;;) {
                      sp.write("foo\r\n");
                      if (sp.waitForBytesWritten(1000)) {
                          QByteArray recv;
                          while (sp.waitForReadyRead(1000))
                              recv += sp.readAll();
                          qDebug() << "DATA:" << recv;
                      } else {
                          qDebug() << "WR OOPS:" << sp.error();
                      }
                  }
                  return a.exec();
              }
              

              and it does work for me.

              This example opens the COM3, send the 'foo' data and waits for the response. On other side I had open the Putty on the COM4, and put some symbols there.. And I see all received data on the COM3.

              1 Reply Last reply
              4
              • R Offline
                R Offline
                rasc
                wrote on last edited by rasc
                #9

                I now checked with the blockingmaster example https://doc.qt.io/qt-5/qtserialport-blockingmaster-example.html. With 5.13.2 the example code works, with 5.14.0 onwards it does not. So it doesn't seem to be a problem of my code (I was a bit afraid that it could be a threading issue, but the blocking master example only uses a single thread and still doesn't work).

                I see that waitForReadyRead(1000) always runs into a timeout no matter the value and never resolves, so readAll() is never called. However, when I run readAll() anyway, it correctly catches the answer from the device. So communication actually works, but waitForReadyRead() seems to be broken for me.

                What makes this especially weird is that the readyRead() signal seems to be emitted correctly, since this code

                QEventLoop loop;
                auto connection = QWidget::connect(
                    this,
                    &QSerialPort::readyRead,
                    &loop,
                    &QEventLoop::quit
                );
                write(request.c_str());
                loop.exec();
                

                correctly runs through and reading afterwards gives (a part) of the devices answer. I am a bit lost now, why waitForReadyRead() does not work.

                JonBJ 1 Reply Last reply
                0
                • R rasc

                  I now checked with the blockingmaster example https://doc.qt.io/qt-5/qtserialport-blockingmaster-example.html. With 5.13.2 the example code works, with 5.14.0 onwards it does not. So it doesn't seem to be a problem of my code (I was a bit afraid that it could be a threading issue, but the blocking master example only uses a single thread and still doesn't work).

                  I see that waitForReadyRead(1000) always runs into a timeout no matter the value and never resolves, so readAll() is never called. However, when I run readAll() anyway, it correctly catches the answer from the device. So communication actually works, but waitForReadyRead() seems to be broken for me.

                  What makes this especially weird is that the readyRead() signal seems to be emitted correctly, since this code

                  QEventLoop loop;
                  auto connection = QWidget::connect(
                      this,
                      &QSerialPort::readyRead,
                      &loop,
                      &QEventLoop::quit
                  );
                  write(request.c_str());
                  loop.exec();
                  

                  correctly runs through and reading afterwards gives (a part) of the devices answer. I am a bit lost now, why waitForReadyRead() does not work.

                  JonBJ Offline
                  JonBJ Offline
                  JonB
                  wrote on last edited by
                  #10

                  @rasc said in QSerialPort readAll() does not work with 5.14.0 anymore:

                  I am a bit lost now, why waitForReadyRead() does not work.

                  I wrote you earlier:

                  The waitFor...()s are a bit "dodgy".

                  You have never said what platform you are on. Docs used to say waitFor...s were "dodgy" under Windows at least, though I believe that has been removed, so maybe they are supposed to be robust now. But your experiences seem to indicate.....

                  R 1 Reply Last reply
                  1
                  • JonBJ JonB

                    @rasc said in QSerialPort readAll() does not work with 5.14.0 anymore:

                    I am a bit lost now, why waitForReadyRead() does not work.

                    I wrote you earlier:

                    The waitFor...()s are a bit "dodgy".

                    You have never said what platform you are on. Docs used to say waitFor...s were "dodgy" under Windows at least, though I believe that has been removed, so maybe they are supposed to be robust now. But your experiences seem to indicate.....

                    R Offline
                    R Offline
                    rasc
                    wrote on last edited by
                    #11

                    @JonB said in QSerialPort readAll() does not work with 5.14.0 anymore:

                    I wrote you earlier:

                    The waitFor...()s are a bit "dodgy".

                    Yes, that's for sure true.
                    I am indeed on Windows, but it has worked fine so far until 5.14.0.

                    Moving to signal/slots is sure possible, but probably requires quite a bit of work. I call the receive function in a for loop to control a translation stage on my microscope and raster a sample, so it has to work synchronously at the moment. Moving to signal/slots means changing how I control the stage. Also, I wanted to understand why it broke.

                    Thanks for the help, I guess signal/slots is the only solution now.

                    JonBJ 1 Reply Last reply
                    0
                    • R rasc

                      @JonB said in QSerialPort readAll() does not work with 5.14.0 anymore:

                      I wrote you earlier:

                      The waitFor...()s are a bit "dodgy".

                      Yes, that's for sure true.
                      I am indeed on Windows, but it has worked fine so far until 5.14.0.

                      Moving to signal/slots is sure possible, but probably requires quite a bit of work. I call the receive function in a for loop to control a translation stage on my microscope and raster a sample, so it has to work synchronously at the moment. Moving to signal/slots means changing how I control the stage. Also, I wanted to understand why it broke.

                      Thanks for the help, I guess signal/slots is the only solution now.

                      JonBJ Offline
                      JonBJ Offline
                      JonB
                      wrote on last edited by
                      #12

                      @rasc
                      I take the point, and I hope my answering has not dissuaded others chiming in if they know. Personally I don't know if there is anything wrong in your wait code. You may wish to raise this as Qt bug if you feel they may be able to help.

                      R 1 Reply Last reply
                      0
                      • mrjjM Offline
                        mrjjM Offline
                        mrjj
                        Lifetime Qt Champion
                        wrote on last edited by mrjj
                        #13

                        Hi
                        I would wait with Qt bug report until @kuzulis answers. After all he wrote the class. :)

                        1 Reply Last reply
                        1
                        • JonBJ JonB

                          @rasc
                          I take the point, and I hope my answering has not dissuaded others chiming in if they know. Personally I don't know if there is anything wrong in your wait code. You may wish to raise this as Qt bug if you feel they may be able to help.

                          R Offline
                          R Offline
                          rasc
                          wrote on last edited by
                          #14

                          @JonB

                          Personally I don't know if there is anything wrong in your wait code.

                          Well, I basically copied the example code and the blockingmaster example doesn't work anymore either. So something in the behavior of QSerialPort has changed from 5.13.2 to 5.14.0 onwards. If it is an intended change or not, I don't dare to judge. If @kuzulis wrote the class, I guess he is the best expert on this. :)

                          K 1 Reply Last reply
                          0
                          • K Offline
                            K Offline
                            kuzulis
                            Qt Champions 2020
                            wrote on last edited by
                            #15

                            @rasc said in QSerialPort readAll() does not work with 5.14.0 anymore:

                            waitForReadyRead() seems to be broken for me.

                            It is possible that now the waitForBytesWritten() handles the read pending requests too.. So, you may try to check that the new data are available after the waitForBytesWritten() call.

                            1 Reply Last reply
                            2
                            • R rasc

                              @JonB

                              Personally I don't know if there is anything wrong in your wait code.

                              Well, I basically copied the example code and the blockingmaster example doesn't work anymore either. So something in the behavior of QSerialPort has changed from 5.13.2 to 5.14.0 onwards. If it is an intended change or not, I don't dare to judge. If @kuzulis wrote the class, I guess he is the best expert on this. :)

                              K Offline
                              K Offline
                              kuzulis
                              Qt Champions 2020
                              wrote on last edited by kuzulis
                              #16

                              @rasc said in QSerialPort readAll() does not work with 5.14.0 anymore:

                              I basically copied the example code and the blockingmaster example doesn't work anymore either.

                              For me it does work with the virtual com0com serial ports. :)

                              A main issue is that it is hard to reproduce this problem to create the auto-tests. And yes, the waitForXXX() methods it is devil methods, it would be good to remove this at all and keep only the asynchronous API.

                              @rasc said in QSerialPort readAll() does not work with 5.14.0 anymore:

                              So something in the behavior of QSerialPort has changed from 5.13.2 to 5.14.0

                              Yes, there are a main change is that now the I/O uses the Windows alertable functions, like {Read|Write}FileEx() instead of previous {Read|Write}File() && QWinOverlapepdIONotifier (which was buggy and removed too).

                              1 Reply Last reply
                              2
                              • K Offline
                                K Offline
                                kuzulis
                                Qt Champions 2020
                                wrote on last edited by kuzulis
                                #17

                                A better solution is to use the asynchronous approach with the signals. :)

                                UPD: The QSP already has the similar 'blocking' auto-test, but it does not reproduces the problem for me:

                                    // first stage
                                    senderPort.write(newlineArray);
                                    senderPort.waitForBytesWritten(waitMsecs);
                                    QTest::qSleep(waitMsecs);
                                    receiverPort.waitForReadyRead(waitMsecs);
                                    QCOMPARE(receiverPort.bytesAvailable(), qint64(newlineArray.size()));
                                
                                    receiverPort.write(receiverPort.readAll());
                                    receiverPort.waitForBytesWritten(waitMsecs);
                                    QTest::qSleep(waitMsecs);
                                    senderPort.waitForReadyRead(waitMsecs);
                                    QCOMPARE(senderPort.bytesAvailable(), qint64(newlineArray.size()));
                                    QCOMPARE(senderPort.readAll(), newlineArray);
                                
                                1 Reply Last reply
                                2
                                • K Offline
                                  K Offline
                                  kuzulis
                                  Qt Champions 2020
                                  wrote on last edited by
                                  #18

                                  This test passes for me with the com0com serial port (I have not the USB/Serial adapters):

                                  void tst_QSerialPort::twoStageSynchronousLoopback()
                                  {
                                      QSerialPort senderPort(m_senderPortName);
                                      QVERIFY(senderPort.open(QSerialPort::ReadWrite));
                                  
                                      QSerialPort receiverPort(m_receiverPortName);
                                      QVERIFY(receiverPort.open(QSerialPort::ReadWrite));
                                  
                                      const int waitMsecs = 50;
                                  
                                      // first stage
                                      QVERIFY(senderPort.write(newlineArray) > 0);
                                      QVERIFY(senderPort.waitForBytesWritten(waitMsecs));
                                      QTest::qSleep(waitMsecs);
                                      QVERIFY(receiverPort.waitForReadyRead(waitMsecs));
                                      QCOMPARE(receiverPort.bytesAvailable(), qint64(newlineArray.size()));
                                  
                                      QVERIFY(receiverPort.write(receiverPort.readAll()) > 0);
                                      QVERIFY(receiverPort.waitForBytesWritten(waitMsecs));
                                      QTest::qSleep(waitMsecs);
                                      QVERIFY(senderPort.waitForReadyRead(waitMsecs));
                                      QCOMPARE(senderPort.bytesAvailable(), qint64(newlineArray.size()));
                                      QCOMPARE(senderPort.readAll(), newlineArray);
                                  
                                      // second stage
                                      QVERIFY(senderPort.write(newlineArray) > 0);
                                      QVERIFY(senderPort.waitForBytesWritten(waitMsecs));
                                      QTest::qSleep(waitMsecs);
                                      QVERIFY(receiverPort.waitForReadyRead(waitMsecs));
                                      QCOMPARE(receiverPort.bytesAvailable(), qint64(newlineArray.size()));
                                      QVERIFY(receiverPort.write(receiverPort.readAll()) > 0);
                                      QVERIFY(receiverPort.waitForBytesWritten(waitMsecs));
                                      QTest::qSleep(waitMsecs);
                                      QVERIFY(senderPort.waitForReadyRead(waitMsecs));
                                      QCOMPARE(senderPort.bytesAvailable(), qint64(newlineArray.size()));
                                      QCOMPARE(senderPort.readAll(), newlineArray);
                                  }
                                  
                                  1 Reply Last reply
                                  1
                                  • R Offline
                                    R Offline
                                    rasc
                                    wrote on last edited by
                                    #19

                                    @kuzulis Thanks for all your feedback. I for sure trust you that your auto-tests all pass. However, they don't seem to test for the issue I have, which might very well be related to how the hardware I have behaves.

                                    I followed your idea to test for available data after the waitForBytesWritten() call. I did

                                    write(data);
                                    if (waitForBytesWritten(1000)) {
                                    	flush();		// just for testing, doesn't change anything
                                    	auto available1 = bytesAvailable(); // <- yields 0
                                    	waitForReadyRead(10000);	// <- runs into timeout
                                    	auto available2 = bytesAvailable(); // <- yields correct length
                                    	auto result = readAll();	// yields correct data
                                    }
                                    

                                    So the data is in the read buffer, but waitForReadyRead() is not notified about that.

                                    JonBJ 1 Reply Last reply
                                    1
                                    • R rasc

                                      @kuzulis Thanks for all your feedback. I for sure trust you that your auto-tests all pass. However, they don't seem to test for the issue I have, which might very well be related to how the hardware I have behaves.

                                      I followed your idea to test for available data after the waitForBytesWritten() call. I did

                                      write(data);
                                      if (waitForBytesWritten(1000)) {
                                      	flush();		// just for testing, doesn't change anything
                                      	auto available1 = bytesAvailable(); // <- yields 0
                                      	waitForReadyRead(10000);	// <- runs into timeout
                                      	auto available2 = bytesAvailable(); // <- yields correct length
                                      	auto result = readAll();	// yields correct data
                                      }
                                      

                                      So the data is in the read buffer, but waitForReadyRead() is not notified about that.

                                      JonBJ Offline
                                      JonBJ Offline
                                      JonB
                                      wrote on last edited by JonB
                                      #20

                                      @rasc
                                      I assume you tested this under 5.15.1? Can you confirm to @kuzulis that you have also tried just this code under 5.13.2 and it does not timeout on your waitForReadyRead(10000); // <- runs into timeout?

                                      1 Reply Last reply
                                      0
                                      • R Offline
                                        R Offline
                                        rasc
                                        wrote on last edited by
                                        #21

                                        @JonB Sorry if I have been unclear here.
                                        The code above runs fine on 5.13.2 (Win), no timeout and waitForReadyRead(10000); returns true.
                                        The very same code on 5.15.0 (Win) runs into the timeout and waitForReadyRead(10000); returns false.

                                        JonBJ 1 Reply Last reply
                                        1
                                        • R rasc

                                          @JonB Sorry if I have been unclear here.
                                          The code above runs fine on 5.13.2 (Win), no timeout and waitForReadyRead(10000); returns true.
                                          The very same code on 5.15.0 (Win) runs into the timeout and waitForReadyRead(10000); returns false.

                                          JonBJ Offline
                                          JonBJ Offline
                                          JonB
                                          wrote on last edited by JonB
                                          #22

                                          @rasc
                                          Hopefully @kuzulis will read this and may have a comment to make!

                                          I will just say this is why I have never used to waitFor...() methods, as stated earlier!

                                          R 1 Reply Last reply
                                          0

                                          • Login

                                          • Login or register to search.
                                          • First post
                                            Last post
                                          0
                                          • Categories
                                          • Recent
                                          • Tags
                                          • Popular
                                          • Users
                                          • Groups
                                          • Search
                                          • Get Qt Extensions
                                          • Unsolved