My application has to communicate with a custom device through a handshake protocol which provides for a response (ACK or NACK) for every packet/command sent in both directions. Every packets/commands start with 0x02 marker, then two byte for the size, then the type, then data and finally the close marker 0x03. I've created a separate class for the serial communication with `QSerialPort` and created the signals/slots needed:

Qt Code:
  1. connect( myInterface, &MyInterface::SendPacket, serialConnection, &SerialConnection::SendPacket, Qt::DirectConnection );
  2. connect( myInterface, &MyInterface::SendAck, serialConnection, &SerialConnection::SendAck, Qt::DirectConnection );
  3. connect( myInterface, &MyInterface::SendNack, serialConnection, &SerialConnection::SendNack, Qt::DirectConnection );
  4. connect( serialConnection, &SerialConnection::ReceivePacket, myInterface, &MyInterface::ReceivePacket, Qt::DirectConnection );
  5. connect( serialConnection, &SerialConnection::ReceiveAck, myInterface, &MyInterface::ReceiveAck, Qt::DirectConnection );
  6. connect( serialConnection, &SerialConnection::ReceiveNack, myInterface, &MyInterface::ReceiveNack, Qt::DirectConnection );
To copy to clipboard, switch view to plain text mode 

Following my serial communication class (I've omitted the unnecessary parts of code) :

serialconnection.cpp
Qt Code:
  1. SerialConnection::SerialConnection( QWidget *parent ) :
  2. QWidget( parent ),
  3. serial( new QSerialPort )
  4. {
  5. connect( serial, &QSerialPort::readyRead, this, &SerialConnection::ReadData );
  6. }
  7.  
  8. SerialConnection::~SerialConnection()
  9. {
  10.  
  11. }
  12.  
  13. void SerialConnection::SendAck()
  14. {
  15.  
  16. [...]
  17.  
  18. serial->write( ack );
  19. qDebug() << "-> ack";
  20. }
  21.  
  22. void SerialConnection::SendNack()
  23. {
  24. QByteArray nack;
  25.  
  26. [...]
  27.  
  28. serial->write( nack );
  29. qDebug() << "-> nack";
  30. }
  31.  
  32. void SerialConnection::SendPacket( QByteArray packet )
  33. {
  34. serial->write( packet );
  35. qDebug() << "-> " + packet.toHex();
  36. }
  37.  
  38. void SerialConnection::ReadData()
  39. {
  40. [...]
  41. if ( packet.at( 3 ) == COMMUNICATION_USB_PACKET_TYPE_ACK )
  42. {
  43. qDebug() << "<- ack";
  44. emit ReceiveAck();
  45. }
  46. else if ( packet.at( 3 ) == COMMUNICATION_USB_PACKET_TYPE_NACK )
  47. {
  48. qDebug() << "<- nack";
  49. emit ReceiveNack();
  50. }
  51. else
  52. {
  53. qDebug() << "<- packet: " + packet.toHex();
  54. emit ReceivePacket( packet );
  55. }
  56. }
To copy to clipboard, switch view to plain text mode 

and my interface class:

myinterface.cpp
Qt Code:
  1. MyInterface::MyInterface( QWidget *parent ) :
  2. QWidget( parent ),
  3. ui( new Ui::MyInterface )
  4. {
  5. ui->setupUi( this );
  6.  
  7. connect( ui->pushButtonTest, &QPushButton::clicked, this, &MyInterface::Test );
  8. }
  9.  
  10.  
  11. void Onemytis2Interface::ReceiveAck()
  12. {
  13. ackReceived = true;
  14. }
  15.  
  16. void Onemytis2Interface::ReceiveNack()
  17. {
  18. nackReceived = true;
  19. }
  20.  
  21. void Onemytis2Interface::ReceivePacket( QByteArray packet )
  22. {
  23. switch ( packet.at( 4 ) )
  24. {
  25. case COMMUNICATION_USB_RX_COMMAND_DEVICE_SERIAL_NUMBER_GET:
  26. {
  27. if ( packet.size() == COMMUNICATION_USB_RX_COMMAND_DEVICE_SERIAL_NUMBER_GET_SIZE )
  28. {
  29. emit SendAck();
  30. deviceSerialNumber = packet.mid( 5, 16 );
  31. ui->labelSNValue->setText( deviceSerialNumber );
  32. requestReceived = true;
  33. }
  34. else
  35. {
  36. emit SendNack();
  37. }
  38.  
  39. break;
  40. }
  41.  
  42. case COMMUNICATION_USB_RX_COMMAND_DEVICE_TYPE_GET:
  43. {
  44. if ( packet.size() == COMMUNICATION_USB_RX_COMMAND_DEVICE_TYPE_GET_SIZE )
  45. {
  46. emit SendAck();
  47. deviceType = packet.mid( 5, 16 );
  48. ui->labelModelValue->setText( deviceType );
  49. requestReceived = true;
  50. }
  51. else
  52. {
  53. emit SendNack();
  54. }
  55.  
  56. break;
  57. }
  58.  
  59. case COMMUNICATION_USB_RX_COMMAND_TEST:
  60. {
  61.  
  62. break;
  63. }
  64.  
  65. default:
  66. {
  67. qDebug() << "ERROR";
  68. break;
  69. }
  70. }
  71. }
  72.  
  73.  
  74. void MyInterface::Test()
  75. {
  76. RequestType();
  77. RequestSerialNumber();
  78. }
  79.  
  80.  
  81. void MyInterface::RequestType()
  82. {
  83. QByteArray request;
  84. QByteArray cmdSize;
  85. uint16_t cmdSizeTmp;
  86. int retry;
  87.  
  88. request.append( ( char ) COMMUNICATION_USB_PACKET_STX );
  89. request.append( ( char ) 0x00 );
  90. request.append( ( char ) 0x00 );
  91. request.append( ( char ) COMMUNICATION_USB_PACKET_TYPE_COMMAND );
  92. request.append( ( char ) COMMUNICATION_USB_TX_COMMAND_DEVICE_TYPE_GET );
  93. request.append( ( char ) COMMUNICATION_USB_PACKET_ETX );
  94.  
  95. cmdSizeTmp = request.length();
  96. cmdSize.append( *( char * )&cmdSizeTmp );
  97. cmdSize.append( *( ( char * )&cmdSizeTmp + 1 ) );
  98. request.replace( 1, 2, cmdSize );
  99.  
  100. ackReceived = false;
  101. nackReceived = false;
  102. requestReceived = false;
  103. emit SendPacket( request );
  104.  
  105. retry = 0;
  106.  
  107. while ( ackReceived == false && nackReceived == false )
  108. {
  109. retry++;
  110. QThread::msleep( 1 );
  111.  
  112. if ( retry > COMMUNICATION_USB_PACKET_WAIT_MAX_MS )
  113. {
  114. qDebug() << "timeout type response";
  115. break;
  116. }
  117. }
  118.  
  119. if ( ackReceived == true )
  120. {
  121. retry = 0;
  122.  
  123. while ( requestReceived == false )
  124. {
  125. retry++;
  126. QThread::msleep( 1 );
  127.  
  128. if ( retry > COMMUNICATION_USB_PACKET_WAIT_MAX_MS )
  129. {
  130. qDebug() << "timeout type request";
  131. break;
  132. }
  133. }
  134. }
  135. else
  136. {
  137. ui->labelTypeValue->setText( "error" );
  138. }
  139. }
  140.  
  141.  
  142. void MyInterface::RequestSerialNumber()
  143. {
  144. QByteArray request;
  145. QByteArray cmdSize;
  146. uint16_t cmdSizeTmp;
  147. int retry;
  148.  
  149. request.append( ( char ) COMMUNICATION_USB_PACKET_STX );
  150. request.append( ( char ) 0x00 );
  151. request.append( ( char ) 0x00 );
  152. request.append( ( char ) COMMUNICATION_USB_PACKET_TYPE_COMMAND );
  153. request.append( ( char ) COMMUNICATION_USB_TX_COMMAND_DEVICE_SERIAL_NUMBER_GET );
  154. request.append( ( char ) COMMUNICATION_USB_PACKET_ETX );
  155.  
  156. cmdSizeTmp = request.length();
  157. cmdSize.append( *( char * )&cmdSizeTmp );
  158. cmdSize.append( *( ( char * )&cmdSizeTmp + 1 ) );
  159. request.replace( 1, 2, cmdSize );
  160.  
  161. ackReceived = false;
  162. nackReceived = false;
  163. requestReceived = false;
  164. emit SendPacket( request );
  165.  
  166. retry = 0;
  167.  
  168. while ( ackReceived == false && nackReceived == false )
  169. {
  170. retry++;
  171. QThread::msleep( 1 );
  172.  
  173. if ( retry > COMMUNICATION_USB_PACKET_WAIT_MAX_MS )
  174. {
  175. qDebug() << "timeout sn response";
  176. break;
  177. }
  178. }
  179.  
  180. if ( ackReceived == true )
  181. {
  182. retry = 0;
  183.  
  184. while ( requestReceived == false )
  185. {
  186. retry++;
  187. QThread::msleep( 1 );
  188.  
  189. if ( retry > COMMUNICATION_USB_PACKET_WAIT_MAX_MS )
  190. {
  191. qDebug() << "timeout sn response";
  192. break;
  193. }
  194. }
  195. }
  196. else
  197. {
  198. ui->labelSNValue->setText( "error" );
  199. }
  200. }
To copy to clipboard, switch view to plain text mode 

Now, if I click the Test push button, I expect the following transactions:

Qt Code:
  1. -> 020600030803 // The interface send the request packet emitting signal in RequestType()
  2. <- ack // The custom device respond with ack, we are waiting it in the RequestType()
  3. <- packet: 02160003034f74686563000000000000000000000003 //The custom device send to interface the requested packet
  4. -> ack // The interface respond with ack
  5. -> 020600030703 // The interface send the request packet emitting signal in RequestSerialNumber()
  6. <- ack // The custom device respond with ack, we are waiting it in the RequestSerialNumber()
  7. <- packet: 02160003034f74686563000000000000000000000003 //The custom device send to interface the requested packet
  8. -> ack // The interface respond with ack
To copy to clipboard, switch view to plain text mode 

but the interface doesn't work as I expect. Usign the `qDebug` I get

Qt Code:
  1. -> 020600030803 // The interface send the request packet emitting signal in RequestType()
  2. timeout type response // I've a timeout waiting the ack/nack for the RequestType() command
  3. -> 020600030703 // The interface send the request packet emitting signal in RequestSerialNumber()
  4. timeout sn response // I've a timeout waiting the ack/nack for the RequestSerialNumber() command
  5. <- ack // HERE I HAVE THE FIRST ACK OF THE RequestType() COMMAND
  6. <- packet: 02160003034f74686563000000000000000000000003
  7. -> ack
  8. <- nack
To copy to clipboard, switch view to plain text mode 

As you can see, I receive the ack for the first command `RequestType()` AFTER the `Test` function terminates and it means after I send two packet, and this cause an error in communication. The state variable `ackReceived`/`nackReceived` never change after emit the `SendPacket` signal if I remain in the call function scope, also if a use a `Qt:irectConnection` between signals and slots.

I've not much experience in the Qt signal/slot context and I want to understand what goin on in my code to achieve my target.

Anyone can give me some suggestions and/or clarifications?