Analog QSerialPort::waitForReadyRead()



  • I need to make a request and get a response from the card through the port. I do not want to wait forever for an answer, so I need to control the timeout. For this, the method QSerialPort::waitForReadyRead() is ideal, but on the Windows platform it has problems. Are there any analogues or alternative solutions? Tried using a timer, but the port was silent.

    QByteArray ComPort::requestResponse(const QByteArray &data)
    {
        mutex->lock();
        qDebug() << "-------------------------";
        if(!serial->isOpen())
            open();
        int attempts = 1;
        QElapsedTimer waitTimer;
        readBuf.clear();
        while (attempts <= 3) {
            if (serial->isWritable())
            {
                serial->write(data);
                waitTimer.restart();
                while (waitTimer.elapsed() < 333){
                    ms_delay(5);
                    readBuf += serial->readAll();
                    if (readBuf.size() == 4){
                        close();
                        mutex->unlock();
                        return readBuf;
                    }
                }
                readBuf.clear();
                qDebug() << "Timeout...";
                close();
                open();
                attempts++;
            }
            else
            {
                qDebug() << "Port is not written";
                close();
                mutex->unlock();
                return 0;
            }
     
        }
        close();
        mutex->unlock();
        return 0;
    }
    

  • Lifetime Qt Champion

    Hi,

    Are you sure the port is opening properly ?

    What if you use Qt's asynchronous capabilities for the communication ?



  • Hi @maratk1n,

    the waitForReady... functions are thought for usage in threads and will not work outside a thread.

    As @SGaist already said, have you thought of the readyRead signal? the timeout could be handled by a QTimer.



  • @SGaist
    I think that it is correctly opened, because if I change

    while (waitTimer.elapsed() < 333){
    //reading
    }
    

    for it,

    while (serial->waitForReadyRead(300)) {    //(wait 300ms). Here, randomly breaks down
    //reading
    }
    

    everything works correctly.
    The asynchronous method is not suitable for two reasons:

    1. I have to receive a response to a specific request, so I need to work synchronously
    2. I must be sure that the board has responded and only then proceed to the next actions


  • @aha_1980
    In these examples (Blocking Master Example, Blocking Slave Example), the method works in other threads (maybe I did not understand the remark).
    In short, it should work like this

    device1.requestResponse(requestPackage)
    //do action 1
    device2.requestResponse(requestPackage)
    //do action 2
    

    Permission to proceed to the following actions only when the board has responded to my request. At the same time, if there is a timeout, I need to resend the request, because maybe the board did not receive a request and wait for a reply is useless


  • Moderators

    @maratk1n said in Analog QSerialPort::waitForReadyRead():

    I have to receive a response to a specific request, so I need to work synchronously
    I must be sure that the board has responded and only then proceed to the next actions

    I don't see why it would not work with asynchronous approach. You send a request and then "wait" until readyRead signal is fired. If you get this signal then you know that the board has responded and it should be the response for the request you sent before.
    If you really want to use blocking calls (waitFor...) then you should move that part to a thread to not to block your main thread.



  • Hi @maratk1n,

    And you should really think if you need to keep a mutex for 300 milliseconds. That effectively makes multithreading impossible.

    But back to your topic: Is your code running in a thread? If the answer is no, then I repeat: it will not work, because with your ms_delay and waitForReadyRead you're blocking Qt's event loop.

    I have written a lot of programs working with QtSerialPort on Windows, and never had problems, neither with non-blocking nor with blocking code. You just have to take care how you use it.


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.