QByte Array for 16 Bytes
-
Hello
I am reading in a 16 Byte stream from a device.
The first byte is always 0x18
The second byte is always 0xFF
And the last byte is always 0x00So I only need a QByteArray of that size (16 Byte)
Does this look correct or is there a cleaner method of setting up my QByte Array?const unsigned char str[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; QByteArray oxy_data(reinterpret_cast<const char*>(&str[0]), std::extent<decltype(str)>::value); oxy_data = serPort->readAll(); qDebug("myVariable : %u ", oxy_data);
-
@nanamo
Stop concentrating on demanding that someQByteArray
(you create) be 16 bytes long and instead concentrate on receiving the actual 16 bytes.Furthermore, you should not rely on any individual call to
readAll()
returning exactly 16 bytes. The way Qt/asynchronous operation works is that each call toreadAll()
could return either the first/next n bytes less than 16, or even that (theoretically) it could return more than the 16 bytes you want if (somehow) a further "message" was sent after the 16 bytes one. This is true even if you know the device sends 16 bytes: Qt does not guarantee that all 16 bytes will be received in a call toreadAll()
.There are a couple of algorithms possible for this. You could buffer the incoming bytes until they reach 16, and then process the first 16, leaving any remainder for future processing. For your purposes I think you could use the following simpler code:
signals: void signal16received(const QByteArray &ba); if (serPort->bytesAvailable() >= 16) { QByteArray ba = serPort->read(16); Q_ASSERT(ba.length() == 16); emit signal16received(ba); }
and attach slot to this signal to process the 16 bytes.
NOTE
@Bonnie's post has crossed with mine. I do not agree with his code [on this occasion, I usually do!], which relies onread(16)
finding all 16 bytes in one call. It will not work correctly if a "packet" of less than 16 bytes arrives, which Qt does not guarantee will not happen. -
@nanamo well ok, but this
oxy_data = serPort->readAll();
completely overrides your previous QByteArray.I wouldn't even be surprised if the compiler optimised these two lines away
const unsigned char str[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; QByteArray oxy_data(reinterpret_cast<const char*>(&str[0]), std::extent<decltype(str)>::value);
-
@JonB Yes I am just creating an array and initializing it to all zeroes.
Then it will be overwritten from reading from the serial port, that is fine.Your method here looks better to create a QByteArray of 16 bytes.
Once it is full I just want to read it and process.
Then it can be overwritten again and I can reread.
Was just wondering the best way to create a 16 byte QByteArray -
@nanamo said in QByte Array for 16 Bytes:
Your method here looks better to create a QByteArray of 16 bytes.
Once it is full I just want to read it and process.
Then it can be overwritten again and I can reread.You do not seem to have understood that your
QByteArray
is not being reused or overwritten. In Qt that rarely happens, instead a newQByteArray
is returned. -
@JonB Oh OK thanks Jon. I understand now. Is there a way to ensure that the QByteArray that is read from the serial port is 16 Bytes long only?
As I need to be able to extract individual bytes from the message.
For example byte 15 is the checksum (8 bit 2s compliment of the sum of bytes 1-14)
So I would like a 16 byte message to work with -
@nanamo
Stop concentrating on demanding that someQByteArray
(you create) be 16 bytes long and instead concentrate on receiving the actual 16 bytes.Furthermore, you should not rely on any individual call to
readAll()
returning exactly 16 bytes. The way Qt/asynchronous operation works is that each call toreadAll()
could return either the first/next n bytes less than 16, or even that (theoretically) it could return more than the 16 bytes you want if (somehow) a further "message" was sent after the 16 bytes one. This is true even if you know the device sends 16 bytes: Qt does not guarantee that all 16 bytes will be received in a call toreadAll()
.There are a couple of algorithms possible for this. You could buffer the incoming bytes until they reach 16, and then process the first 16, leaving any remainder for future processing. For your purposes I think you could use the following simpler code:
signals: void signal16received(const QByteArray &ba); if (serPort->bytesAvailable() >= 16) { QByteArray ba = serPort->read(16); Q_ASSERT(ba.length() == 16); emit signal16received(ba); }
and attach slot to this signal to process the 16 bytes.
NOTE
@Bonnie's post has crossed with mine. I do not agree with his code [on this occasion, I usually do!], which relies onread(16)
finding all 16 bytes in one call. It will not work correctly if a "packet" of less than 16 bytes arrives, which Qt does not guarantee will not happen. -
@JonB said in QByte Array for 16 Bytes:
@Bonnie's post has crossed with mine. I do not agree with his code, which relies on read(16) finding all 16 bytes in one call. It will not work correctly if a "packet" of less than 16 bytes arrives, which Qt does not guarantee will not happen.
Sure, I haven't considered that much. :)
What I want is just tell OP how to useQByteArray
andread()
. -