Serial communication
-
From my pov the parsing is incorrect as there may be more than one message in the buffer so the second (or even the first part of the second) is thrown away.
@Christian-Ehrlicher so how to fix it?
-
@Christian-Ehrlicher so how to fix it?
@Damian7546
Remove only what is used for a message from the buffer, leaving any further unused bytes there might be for appending to create next "message". -
@Damian7546 Something like this. But better don't use c-style casts:
m_responseStatus = static_cast<Response::Status>(m_request.mid(2,1).toInt(nullptr, 16));
@jsulm
This conversion doesn't work.class Response { public: enum class Status : quint8{ DISABLE = 0x1A, }; Response(); };
In
m_responseStatus
variable I have0x1A
value, but below statement is not equal:m_responseStatus = static_cast<Response::Status>(m_request.mid(2,1).toInt(nullptr, 16)); qDebug() << "m_responseStatus: " << m_request.mid(2,1); if(Response::Status::DISABLE == m_responseStatus) qDebug() << "ok convert"; else qDebug() << "bad convert";
Problem is in
toInt
conversion:qDebug() << "m_responseStatus: " << m_request.mid(2,1); qDebug() << "m_responseStatus: " << m_request.mid(2,1).toInt(nullptr, 16);
result:
m_responseStatus: "\x1A"
m_responseStatus: 0
-
@jsulm
This conversion doesn't work.class Response { public: enum class Status : quint8{ DISABLE = 0x1A, }; Response(); };
In
m_responseStatus
variable I have0x1A
value, but below statement is not equal:m_responseStatus = static_cast<Response::Status>(m_request.mid(2,1).toInt(nullptr, 16)); qDebug() << "m_responseStatus: " << m_request.mid(2,1); if(Response::Status::DISABLE == m_responseStatus) qDebug() << "ok convert"; else qDebug() << "bad convert";
Problem is in
toInt
conversion:qDebug() << "m_responseStatus: " << m_request.mid(2,1); qDebug() << "m_responseStatus: " << m_request.mid(2,1).toInt(nullptr, 16);
result:
m_responseStatus: "\x1A"
m_responseStatus: 0
@Damian7546 said in Serial communication:
In m_responseStatus variable I have 0x1A value, but below statement is not equal:
Sorry, I don't believe that. Start with:
qDebug() << int(m_responseStatus) << int(Response::Status::DISABLE) << 0x1A;
[I assume
int()
is good enough here to test. You can gostatic_cast<int>(...)
if necessary.] -
@Damian7546 said in Serial communication:
In m_responseStatus variable I have 0x1A value, but below statement is not equal:
Sorry, I don't believe that. Start with:
qDebug() << int(m_responseStatus) << int(Response::Status::DISABLE) << 0x1A;
[I assume
int()
is good enough here to test. You can gostatic_cast<int>(...)
if necessary.]@JonB said in Serial communication:
Sorry, I don't believe that. Start with:
qDebug() << int(m_responseStatus) << int(Response::Status::DISABLE) << 0x1A;Result:
0 26 26
-
@JonB said in Serial communication:
Sorry, I don't believe that. Start with:
qDebug() << int(m_responseStatus) << int(Response::Status::DISABLE) << 0x1A;Result:
0 26 26
@Damian7546
So you have your answer from the first 2 outputs.0 != 26
, the two values being compared are indeed not equal/the same.Behaviour is quite correct given your
m_request.mid(2,1).toInt(nullptr, 16);
, which (QByteArray::toInt()) is quite incorrect to use on your byte array containing a byte with value\x16
(26).toInt()
is not for use in your case, as you do not have a string representation of an integer to convert. -
@Damian7546
So you have your answer from the first 2 outputs.0 != 26
, the two values being compared are indeed not equal/the same.Behaviour is quite correct given your
m_request.mid(2,1).toInt(nullptr, 16);
, which (QByteArray::toInt()) is quite incorrect to use on your byte array containing a byte with value\x16
(26).toInt()
is not for use in your case, as you do not have a string representation of an integer to convert.@JonB So ho to compare
Response::Status::DISABLE
to byte in QByteArraym_request[2]
? -
@JonB So ho to compare
Response::Status::DISABLE
to byte in QByteArraym_request[2]
?@Damian7546
Exactly as you have just written it!qDebug() << Response::Status::DISABLE << m_request[2];
[You may have to do casting.] Sightly better is to use
m_request.at(2)
in place ofm_request[2]
here, but that is a detail and not related to your issue. You want to inspect the actual bytes in theQByteArray
, not callQByteArray::toInt()
. -
@Damian7546
Exactly as you have just written it!qDebug() << Response::Status::DISABLE << m_request[2];
[You may have to do casting.] Sightly better is to use
m_request.at(2)
in place ofm_request[2]
here, but that is a detail and not related to your issue. You want to inspect the actual bytes in theQByteArray
, not callQByteArray::toInt()
. -
@JonB casting is highly suggested, as
Response::Status
is an uint_8t and at() returns a char, aka int8_t@J-Hilk
Yes, but what I meant is I don't have anything available to test what compiler says as I write answers. So that detail is left to OP :) Since the OP asks about comparing (with==
) one should be able to compare aunit_8t
against achar
/int8_t
, I think, using C++ automatic expression promotion without bothering to cast/convert, I think? But maybe not/warning forenum
value against integer?The important thing is no
QByteArray::toInt()
here! -
@J-Hilk
Yes, but what I meant is I don't have anything available to test what compiler says as I write answers. So that detail is left to OP :) Since the OP asks about comparing (with==
) one should be able to compare aunit_8t
against achar
/int8_t
, I think, using C++ automatic expression promotion without bothering to cast/convert, I think? But maybe not/warning forenum
value against integer?The important thing is no
QByteArray::toInt()
here!@JonB It doesn't work:
qDebug() << static_cast<int>(Response::Status::DISABLE) << m_request.at(2);
Result:
ASSERT: "uint(i) < uint(size())" in file C:/Qt/5.15.2/mingw81_32/include/QtCore/qbytearray.h, line 500
And this way:
qDebug() << static_cast<int>(Response::Status::DISABLE) << m_request[2];
Result:
Where :
m_request response: "\xFC\x05\x1A\xF4\xE8"
-
@JonB It doesn't work:
qDebug() << static_cast<int>(Response::Status::DISABLE) << m_request.at(2);
Result:
ASSERT: "uint(i) < uint(size())" in file C:/Qt/5.15.2/mingw81_32/include/QtCore/qbytearray.h, line 500
And this way:
qDebug() << static_cast<int>(Response::Status::DISABLE) << m_request[2];
Result:
Where :
m_request response: "\xFC\x05\x1A\xF4\xE8"
@Damian7546
How difficult to try:qDebug() << static_cast<int>(Response::Status::DISABLE) << static_cast<int>(m_request[2]); // or qDebug() << static_cast<int>(Response::Status::DISABLE) << static_cast<int>(m_request.at(2));
? I leave you to resolve the C++ to your satisfaction.
-
@J-Hilk
Yes, but what I meant is I don't have anything available to test what compiler says as I write answers. So that detail is left to OP :) Since the OP asks about comparing (with==
) one should be able to compare aunit_8t
against achar
/int8_t
, I think, using C++ automatic expression promotion without bothering to cast/convert, I think? But maybe not/warning forenum
value against integer?The important thing is no
QByteArray::toInt()
here!@JonB said in Serial communication:
one should be able to compare a unit_8t against a char/int8_t, I think, using C++ automatic expression promotion without bothering to cast/convert, I think?
nono, comparing different types via == or != will never promote any side "automatically"
you can get something like that fi you wrap it in a function call or something but.
But comparing uint8_t and int_8 will only work correctly if both values are between 0 and 128.
-
@Damian7546
How difficult to try:qDebug() << static_cast<int>(Response::Status::DISABLE) << static_cast<int>(m_request[2]); // or qDebug() << static_cast<int>(Response::Status::DISABLE) << static_cast<int>(m_request.at(2));
? I leave you to resolve the C++ to your satisfaction.
@JonB Sill of topic.
I have variable:Response::Status m_responseStatus
.
How properly assign byte form QByteArray to m_responseStatus? -
@JonB Sill of topic.
I have variable:Response::Status m_responseStatus
.
How properly assign byte form QByteArray to m_responseStatus?@Damian7546 you were originally pretty spot on:
static_cast<Response::Status>(m_request.at(0));
-
@JonB said in Serial communication:
one should be able to compare a unit_8t against a char/int8_t, I think, using C++ automatic expression promotion without bothering to cast/convert, I think?
nono, comparing different types via == or != will never promote any side "automatically"
you can get something like that fi you wrap it in a function call or something but.
But comparing uint8_t and int_8 will only work correctly if both values are between 0 and 128.
@J-Hilk said in Serial communication:
nono, comparing different types via == or != will never promote any side "automatically"
Umm, C or C++
char c('A'); if (c == 65) {} example.cpp Compiler returned: 0
From Godbolt. That's "automatically promoting"
char c
toint 65
, per C/C++ expression rules. Has done since K&R... ?
https://en.cppreference.com/w/cpp/language/implicit_conversion, e.g. Integral conversions topic. -
@Damian7546 you were originally pretty spot on:
static_cast<Response::Status>(m_request.at(0));
@J-Hilk said in Serial communication:
static_cast<Response::Status>(m_request.at(0));
I trust healthy disagreement in polite spirit is allowed. Personally, for style, I would not cast an arbitrary integer value to an enumeration, where it might fall outside the range of values. I would prefer
if (static_cast<int>(Response::Status::DISABLE) == static_cast<int>(m_request.at(2))
which is what I wrote earlier, so doing the casting to
int
. -
@J-Hilk said in Serial communication:
static_cast<Response::Status>(m_request.at(0));
I trust healthy disagreement in polite spirit is allowed. Personally, for style, I would not cast an arbitrary integer value to an enumeration, where it might fall outside the range of values. I would prefer
if (static_cast<int>(Response::Status::DISABLE) == static_cast<int>(m_request.at(2))
which is what I wrote earlier, so doing the casting to
int
.@JonB said in Serial communication:
which is what I wrote earlier, so doing the casting to int.
yes I agree, but not what the op asked.
From Godbolt. That's "automatically promoting" char c to int 65, per C/C++ expression rules. Has done since K&R... ?
fair! Not what I had in mind when I wrote my answer and not the pitfall I fell into numerous times :D
-
@Damian7546 you were originally pretty spot on:
static_cast<Response::Status>(m_request.at(0));
@J-Hilk It still doesn't work:
m_responseStatus = static_cast<Response::Status>(m_request.at(2));
Result:
ASSERT: "uint(i) < uint(size())" in file C:/Qt/5.15.2/mingw81_32/include/QtCore/qbytearray.h, line 500
-
@J-Hilk It still doesn't work:
m_responseStatus = static_cast<Response::Status>(m_request.at(2));
Result:
ASSERT: "uint(i) < uint(size())" in file C:/Qt/5.15.2/mingw81_32/include/QtCore/qbytearray.h, line 500
@Damian7546 yes, but not the cast or assignment fails, but the access of your QByteArray, it doesn't have 3 Bytes in it and you try to access it outside of the range