How read correct data from QSerialPort



  • Hello I have problem with reading correct answer from serial port.
    I send command to device - XXX
    and device respond me number between 0 - 1023.
    I use this code but it's not good idea I think beacuse I always read 3 digit.

    serialPort->write("XXX\n");
    QByteArray data = serialPort->read(3);
    

    Answer:

    "320"
    "33"
    "1"
    ""
    "333"
    

    I want read only correct number, I use timer to send command



  • Please download, run and watch how this software is written to have an idea now how to use serial ports in Qt.

    https://www.linux-apps.com/p/1127795/



  • QSerialPort::read(qint64 maxSize) only reads up to the number of bytes specified. You cannot assume it will return 3 bytes --- it could read between 1 and 3 bytes (I'm not sure about 0), depending on what is available.

    Read http://doc.qt.io/qt-5/qserialport.html#details carefully. You may need any combination of

    • for reading: repeated read()s, readAll(), waitForReadyRead(), bytesAvailable()
    • for writing: waitForBytesWritten(), flush()

    P.S.

    and device respond me number between 0 - 1023.
    I use this code but it's not good idea I think beacuse I always read 3 digit

    Values >= 1000 will not fit into 3 bytes!


  • Moderators

    @erytcg You should connect a slot to http://doc.qt.io/qt-5/qiodevice.html#readyRead signal of your serial port and read the data there using readAll(). Else it will not work. You can't just read at any random time.



  • @jsulm said in How read correct data from QSerialPort:

    @erytcg You should connect a slot to http://doc.qt.io/qt-5/qiodevice.html#readyRead signal of your serial port and read the data there using readAll(). Else it will not work. You can't just read at any random time.

    Even then, just because readyRead signal is emitted it won't necessarily mean that > 1 byte is available to read, will it?


  • Moderators

    @JNBarchan No. That's why it is even more complex: one should read until everything was received and buffer the data.



  • @jsulm
    As @jsulm says, the usual technique here is: you write your own "wrapper" around the reads (e.g. in readyRead signal handler), in which you copy the bytes received into your own buffer. Then the caller reads out of that buffer, not direct from the port. You keep a note of how many bytes have been read into the buffer, and where the "read pointer" is currently which gets incremented as bytes are read. You could derive from QSerialPort to do this, or just write utility functions.



  • @JNBarchan said in How read correct data from QSerialPort:

    n which you copy the bytes received into your own buffer.

    It is unnecessary, as all data are cached in buffer inside of QSP. Just use peek() && bytesAvailable() && read() to parse a data.



  • @kuzulis said in How read correct data from QSerialPort:

    @JNBarchan said in How read correct data from QSerialPort:

    n which you copy the bytes received into your own buffer.

    It is unnecessary, as all data are cached in buffer inside of QSP. Just use peek() && bytesAvailable() && read() to parse a data.

    That's not the point. The goal is to accumulate the input into your own buffer, so that you can control the reading of full data.



  • @JNBarchan said in How read correct data from QSerialPort:

    That's not the point. The goal is to accumulate the input into your own buffer, so that you can control the reading of full data.

    You do not need in a separate buffer for that purpose. The QSP's buffer already accumulates all data. Just read required portions of data from QSP.



  • @kuzulis I do not agree with your approach.

    It may work as the OP has phrased his question. However, consider the following protocol:

    • Since he already does not know whether the device returns between 1 and 4 bytes for number 1 to 1024, he changes the protocol to put a \n terminator at the end of the response.
    • So he does not know how many bytes received constitute a "complete" response.
    • If bytesAvailable() returns 1, and read returns that byte, what does he do with that byte, given that he has to wait for more bytes before it's a number he can convert? he will end up having to buffer it. Which is why a buffered wrapper around the reads is the neatest solution.

    BTW, this buffering is the same approach as used by all C runtimes for reading bytes from a FILE. It does not return the underlying OS read buffer. This makes, say, fscanf(fp, "%d") a lot easier to implement than if the underlying read buffer was returned without buffered wrapping...



  • Tomorrow I will check if my device is sending "\n" after answer. Now helped, setting timer interval for more than 0.



  • Have you got a document with the device protocol?
    Normally there is a start and stop byte, a crc byte ....



  • @erytcg You didn't tell us you were only using 0 in your timer delay! It may indeed work (better) if you put in a delay, though it's still "naughty" code! Don't forget to look at your protocol, because the way you have specified it the device won't be able to send back 3 bytes for a numbers 1000 to 1023, and for numbers < 100 it had better be padding with leading zeroes... !



  • @JNBarchan said in How read correct data from QSerialPort:

    If bytesAvailable() returns 1, and read returns that byte

    Why do you need to use read()? Use peek() to look to that byte. If that byte in not 'delimiter', then just drop this byte using read().

    PS: Besides, if the user used correct '\n' delimiters, then I do not see any problems at all, just use canReadLine() && readLine().

    PS2: I repeat again: QSP already is buffered! Do you understand it? You do not need in separate buffer in common case (but, you can write own code as you want, I'm don't care about).



  • @kuzulis

    Why do you need to use read()? Use peek() to look to that byte. If that byte in not 'delimiter', then just drop this byte using read().

    You can't "drop" it, it's the first digit of the response, you need to save it somewhere, in order to use it later to parse for the number. Where are you going to put the bytes received so that you can parse the string? That's what the buffer is for.

    PS2: I repeat again: QSP already is buffered! Do you understand it?

    Of course I understand that. My buffering suggestion is not to prevent loss of data, it's a means to easy parsing. I gave the example of C FILE which uses this technique even though the underlying OS read "is already buffered".

    You do not need in separate buffer in common case (but, you can write own code as you want, I'm don't care about).

    Shall we put this down to a difference of opinion/style then and leave it at that? If the OP wants to leave the bytes in the QSP buffer and write code which accumulates bytes directly from there to achieve the goal, that's up to him.


Log in to reply
 

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