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. [SOLVED] QtSerialPort - switching between async/blocking mode
Forum Updated to NodeBB v4.3 + New Features

[SOLVED] QtSerialPort - switching between async/blocking mode

Scheduled Pinned Locked Moved General and Desktop
9 Posts 3 Posters 2.0k 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.
  • A Offline
    A Offline
    AndrzejO
    wrote on last edited by AndrzejO
    #1

    Hello All

    I've got a question about possibility to switch between blocking/async modes for QtSerialPort during reading/writing.
    The problem I'm having is in following setup:

    1. I've got basic communication up and running
    2. On connection to the device I read its configuration (it's a lot of parameters - over 100 - so during connection I use blocking mode and read every parameter - this is in order to simplify program logic)
    3. Then I "switch to asynchronous" mode by connecting to portError() and readyRead() signals and trigger device to send data on its own
    4. Everything goes smoothly until I try to switch configuration (there are up to 8 configuration slots) so I:
      • tell device to switch configuration
      • "wait" asynchronously for it to confirm
      • then I try to switch to "synchronous" mode by disconnecting signals and try to read new configuration via blocking mode

    The last point is where I'm having problems. Everything works perfectly on Linux by on Windows I get following behaviour:

    1. Device acknowledges configuration switch
    2. I disconnect signals
    3. I try to read first parameter via:
        bool ok = true;
        _port->write(cmd);
        _port->waitForBytesWritten(TMOUT);
        while (ok && ! _port->canReadLine())
            ok = _port->waitForReadyRead(TMOUT);
    

    and I always end up with error on waitForReadyRead() (write() & waitForBytesWritten() always complete successfully) and I see portError() callback being called even though I have disconnected it.
    FWIW device is replying correctly for this parameter request (I can see that when I sniff the communication) but somehow it is lost (even the "disconnected" readyRead() callback is not called) and in the portError() callback I get error=9 (ResourceError if I can count to 10 :))

    Does anybody know how I can switch between blocking/asynchronous modes on Windows?

    Best regards
    Andrzej

    1 Reply Last reply
    0
    • SGaistS Offline
      SGaistS Offline
      SGaist
      Lifetime Qt Champion
      wrote on last edited by
      #2

      Hi and welcome to devnet,

      Strange effect indeed, can you show your connect and disconnect code ?

      Interested in AI ? www.idiap.ch
      Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

      1 Reply Last reply
      0
      • A Offline
        A Offline
        AndrzejO
        wrote on last edited by
        #3

        First of all thank you for your interest, and apologies for getting back so late (I expected some mail notification that someone has replied and found your reply only now - is it possible to configure this forum to notify about replies?).

        Here's the function in question.

        void Driver::asyncMode(bool is_async)
        {
            if (is_async) {
                connect(_port, &QSerialPort::readyRead, this, &Driver::readyRead);
                connect(_port, static_cast<void(QSerialPort::*)(QSerialPort::SerialPortError)>(&QSerialPort::error),
                        this,  &Driver::portError);
            } else
                _port->disconnect();
        }
        

        Actually during searching for solution I've managed to prepare sample code that shows even problems with basic usage of waitForReadyRead() on Windows. The sample - in a nutshell - is "device" that handles three commands "START" after which it periodically sends time, "STOP" after which it cease to do it and "DATE" for which it replies with value (this is equivalent of my parameters reading in real project).
        Pay not much attention to main.cpp (it's a quick stab at simulating real code behaviour - and here I'm not properly waiting for thread to finish).

        When I'm testing this on virtual com ports on Linux (socat -d -d PTY,raw,echo=0,b115200,cs8 PTY,raw,echo=0,b115200,cs8) I get correct behaviour:


        $ ./async_test /dev/pts/28 /dev/pts/30
        Openning device port
        Openning driver port
        Synchrounous date reading ...
        Read buffer size: 0
        Asking for date ...
        After waitForReadyRead(): true
        Current date: "Thu Jun 11 2015"
        Starting device ...
        void Driver::readyRead() "OK"
        void Driver::readyRead() ":15:58:14"
        void Driver::readyRead() ":15:58:14"
        void Driver::readyRead() ":15:58:15"
        void Driver::readyRead() ":15:58:15"
        void Driver::readyRead() ":15:58:15"
        void Driver::readyRead() ":15:58:16"
        void Driver::readyRead() ":15:58:16"
        void Driver::readyRead() ":15:58:17"
        void Driver::readyRead() ":15:58:17"
        void Driver::readyRead() ":15:58:18"
        Stopping device ...
        void Driver::readyRead() "OK"
        Asking for date ...
        After waitForReadyRead(): true
        Current date: "Thu Jun 11 2015"

        On Windows though (with com0com) I get erroneous behaviour:


        Openning device port
        Openning driver port
        Synchrounous date reading ...
        Read buffer size: 0
        Asking for date ...
        void Driver::readDate() waitForBytesWritten() error: "Parametr jest niepoprawny."
        Starting device ...
        void Driver::readyRead() "Cz cze 11 2015"
        !! Wrong reply for Start: "Cz cze 11 2015"
        void Driver::readyRead() "OK"
        void Driver::readyRead() ":16:01:30"
        void Driver::readyRead() ":16:01:31"
        void Driver::readyRead() ":16:01:31"
        void Driver::readyRead() ":16:01:32"
        void Driver::readyRead() ":16:01:32"
        void Driver::readyRead() ":16:01:33"
        void Driver::readyRead() ":16:01:33"
        void Driver::readyRead() ":16:01:34"
        void Driver::readyRead() ":16:01:34"
        void Driver::readyRead() ":16:01:35"
        Stopping device ...
        void Driver::readyRead() "OK"
        Asking for date ...
        After waitForReadyRead(): false
        void Driver::readDate() waitForReadyRead() error: "Up│yn╣│ limit czasu operacji oczekiwania."

        The errors are reported in Polish and they are more or less "Invalid parameter" and "Timeout".

        Am I missing anything obvious?

        The behaviour I'm seeing is that waitForReadyRead() waits for data and then timeouts with some error (not necessarily "timeout") while the expected data are actually being read (note that after first error on Windows the expected reply for "DATE" command is fed into readyRead() function as a reply for "START" command, for which reply is obtained in next readyRead() invocation).

        If anyone could explain this or point QSerialPort developers to this I'd appreciate.
        Best regards
        Andrzej

        1 Reply Last reply
        0
        • SGaistS Offline
          SGaistS Offline
          SGaist
          Lifetime Qt Champion
          wrote on last edited by SGaist
          #4

          You can find the mail settings here

          @kuzulis might be able to help

          Interested in AI ? www.idiap.ch
          Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

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

            I understood nothing, but if you provided the complete minimum example which reproduces a problem, it would be good (for example, even using the com0com).

            1 Reply Last reply
            0
            • A Offline
              A Offline
              AndrzejO
              wrote on last edited by
              #6

              Thank you kuzulis for devoting your time to look at my problem!

              I already provided sample (the output above is from this sample) and here it is again: sample.

              On Linux (with virtual pair of ports from socat) this code runs without any problem. However on Windows with com0com I see first error from waitForBytesWritten() and then later on waitForReadyRead().

              My original wish is more or less what you see in Driver::readyRead() function. In this callback when I get confirmation from "STOP" command I wanted to switch to "synchronous" mode and read configuration (in sample it is just "DATE" command but in real project this is reading of full configuration which is about 170 params). In there you'll find preprocessor conditional and if you change it then there'll be no problem with reading "DATE" (however I wanted to avoid reading of my configuration that way since it would unnecessarily complicate code).
              So there are two problems with this sample code (on Windows that is, on Linux everything is working OK):

              • why I see error on waitForBytesWritten() in first readyDate() invocation
              • how to call readDate() from readyRead() callback so that it completes without a problem

              Once again thank you for taking your time to look at this.

              Best regards
              Andrzej

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

                Seems you are right.. This is a bug in QSerialPort.

                I found out the reason, please look and try (and to watch and to vote) for the patch: https://codereview.qt-project.org/#/c/115392/

                :)

                1 Reply Last reply
                1
                • A Offline
                  A Offline
                  AndrzejO
                  wrote on last edited by
                  #8

                  Great! I'll take a closer look at it. I hope it will be merged soon (BTW will it be back ported to 5.4, or will it be only in 5.5+) but if voting helps I certainly will vote ... but how do I that :) ?

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

                    or will it be only in 5.5+)

                    This will be released in future Qt 5.5.1 (but not in Qt 5.5.0).. But, in any case, you can build and install the QtSerialPort manually.

                    but if voting helps I certainly will vote ... but how do I that :) ?

                    Yes, please vote for it (+1 or +2) if this works for you. :)

                    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