title: Qt Serial Port - Reading data consistently
body: <p>I am sending (writing) bytes to a device via my serial port. I am using the QSerialPort (<a href="http://qt-project.org/wiki/QtSerialPort" rel="noreferrer">http://qt-project.org/wiki/QtSerialPort</a>) module to instantiate device IO support. When I send messages to my INSTEON modem (serial), upon reading my message the device sends back a copy of my message + 0x06 (ACK Byte) followed by a status message. </p>
  
  <p>I have tested my message using DockLight (<a href="http://www.docklight.de/" rel="noreferrer">http://www.docklight.de/</a>). I send the following message to query the state of the device:</p>
  
  <pre><code>    02 62 1D E9 4B 05 19 00
  </code></pre>
  
  <p>Using Docklight, I receive the response:</p>
  
  <pre><code>    02 62 1D E9 4B 05 19 00 06 02 50 20 CB CF 1E DA F7 21 00 FF
  </code></pre>
  
  <p>The returned message indicates exactly what I would expect, that the device is on. If off, the modem would send back 0x00 in the last byte position if the device was off. Now, my problem - I must not have my function setup properly to send and then receive the response bytes. I have tried many different examples and configurations, currently I am using the following:</p>
  
  <p>Setup signal-slot connections:</p>
  
  <pre><code>QObject::connect(&amp;thread, SIGNAL(sendResponse(QByteArray)), 
      this, SLOT(handleResponse(QByteArray)));
  QObject::connect(&amp;thread, SIGNAL(error(QString)), 
      this, SLOT(processError(QString)));
  QObject::connect(&amp;thread, SIGNAL(timeout(QString)), 
      this, SLOT(processTimeout(QString)));
  </code></pre>
  
  <p>Function used to iterate through QList of devices. If device is desired type ("Light"), then we format the device ID to the intended QByteArray message structure. Pass message to thread for sending. (Thread modified from QSerialPort <code>BlockingMaster</code> example. </p>
  
  <pre><code>void Device::currentStatus(QList&lt;Device *&gt; * deviceList){
      QString devID, updateQry;
      int devStatus, updateStatus;
      updateStatus=0;
      QSqlQuery query;
      for(int i=0; i&lt;deviceList-&gt;size(); i++){
          if(deviceList-&gt;at(i)-&gt;type == "Light"){
              devStatus = deviceList-&gt;at(i)-&gt;status;
              devID = deviceList-&gt;at(i)-&gt;deviceID;
              QByteArray msg;
              bool msgStatus;
              msg.resize(8);
  
              msg[0] = 0x02;
              msg[1] = 0x62;
              msg[2] = 0x00;
              msg[3] = 0x00;
              msg[4] = 0x00;
              msg[5] = 0x05;
              msg[6] = 0x19;
              msg[7] = 0x00;
              msg.replace(2, 3, QByteArray::fromHex( devID.toLocal8Bit() ) );
              qDebug() &lt;&lt; "Has device " &lt;&lt; deviceList-&gt;at(i)-&gt;name &lt;&lt; "Changed?";
              //send(msg,&amp;msgStatus, &amp;updateStatus);
              //msg.clear();
              thread.setupPort("COM3",500,msg);
              if(devStatus!=updateStatus){
                  qDebug() &lt;&lt; deviceList-&gt;at(i)-&gt;name &lt;&lt; " is now: " &lt;&lt; updateStatus;
                  updateStatus = !updateStatus;
              }
          }
      }
  }
  </code></pre>
  
  <p><code>SetupThread</code> function used to set local thread variables and executes (runs) thread.</p>
  
  <pre><code>void serialThread::setupPort(const QString &amp;portName, int waitTimeout, const QByteArray &amp;msg){
      qDebug() &lt;&lt; "Send Message " &lt;&lt; msg.toHex();
      QMutexLocker locker(&amp;mutex);
      this-&gt;portName = portName;
      this-&gt;waitTimeout = waitTimeout;
      this-&gt;msg = msg;
      if(!isRunning())
          start();
      else
          cond.wakeOne();
  }
  </code></pre>
  
  <p><code>Run</code> Function - Handled sending and receiving</p>
  
  <pre><code>void serialThread::run(){
      bool currentPortNameChanged = false;
      qDebug() &lt;&lt; "Thread executed";
      mutex.lock();
      QString currentPortName;
      if(currentPortName != portName){
          currentPortName = portName;
          currentPortNameChanged = true;
      }
  
      int currentWaitTimeout = waitTimeout;
      QByteArray sendMsg = msg;
      mutex.unlock();
      QSerialPort serial;
  
      while(!quit){
          if(currentPortNameChanged){
              serial.close();
              serial.setPortName("COM3");
  
              if (!serial.open(QIODevice::ReadWrite)) {
                  emit error(tr("Can't open %1, error code %2")
                             .arg(portName).arg(serial.error()));
                  return;
              }
  
              if (!serial.setBaudRate(QSerialPort::Baud19200)) {
                  emit error(tr("Can't set baud rate 9600 baud to port %1, error code %2")
                             .arg(portName).arg(serial.error()));
                  return;
              }
  
              if (!serial.setDataBits(QSerialPort::Data8)) {
                  emit error(tr("Can't set 8 data bits to port %1, error code %2")
                             .arg(portName).arg(serial.error()));
                  return;
              }
  
              if (!serial.setParity(QSerialPort::NoParity)) {
                  emit error(tr("Can't set no patity to port %1, error code %2")
                             .arg(portName).arg(serial.error()));
                  return;
              }
  
              if (!serial.setStopBits(QSerialPort::OneStop)) {
                  emit error(tr("Can't set 1 stop bit to port %1, error code %2")
                             .arg(portName).arg(serial.error()));
                  return;
              }
  
              if (!serial.setFlowControl(QSerialPort::NoFlowControl)) {
                  emit error(tr("Can't set no flow control to port %1, error code %2")
                             .arg(portName).arg(serial.error()));
                  return;
              }
          }
  
          //write request
          serial.write(msg);
          if (serial.waitForBytesWritten(waitTimeout)) {
              //! [8] //! [10]
              // read response
              if (serial.waitForReadyRead(currentWaitTimeout)) {
                  QByteArray responseData = serial.readAll();
                  while (serial.waitForReadyRead(10)){
                      responseData += serial.readAll();
                  }
  
                  QByteArray response = responseData;
                  //! [12]
                  emit this-&gt;sendResponse(response);
                  //! [10] //! [11] //! [12]
              } else {
                  emit this-&gt;timeout(tr("Wait read response timeout %1")
                               .arg(QTime::currentTime().toString()));
              }
              //! [9] //! [11]
          } else {
              emit timeout(tr("Wait write request timeout %1")
                           .arg(QTime::currentTime().toString()));
          }
          mutex.lock();
          cond.wait(&amp;mutex);
          if (currentPortName != portName) {
              currentPortName = portName;
              currentPortNameChanged = true;
          } else {
              currentPortNameChanged = false;
          }
          currentWaitTimeout = waitTimeout;
          sendMsg = msg;
          mutex.unlock();
      }
      serial.close();
  }
  </code></pre>
  
  <p><code>handleResponse</code> function, SLOT which receives response signal</p>
  
  <pre><code>void Device::handleResponse(const QByteArray &amp;msg){
      qDebug() &lt;&lt; "Read: " &lt;&lt; msg.toHex();
  }
  </code></pre>
  
  <p>I receive the following output:</p>
  
  <pre><code>Has device  "Living Room Light" Changed? 
  Send Message  "02621de94b051900" 
  Has device  "Bedroom Light" Changed? 
  Send Message  "026220cbcf051900" 
  Thread executed 
  Read:  "026220cbcf05190006" 
  Polling for changes... 
  Has device  "Living Room Light" Changed? 
  Send Message  "02621de94b051900" 
  Has device  "Bedroom Light" Changed? 
  Send Message  "026220cbcf051900" 
  Read:  "025020cbcf1edaf721000002621de94b05190006" 
  Polling for changes... 
  Has device  "Living Room Light" Changed? 
  Send Message  "02621de94b051900" 
  Has device  "Bedroom Light" Changed? 
  Send Message  "026220cbcf051900" 
  Read:  "02501de94b1edaf72100ff02621de94b05190006" 
  </code></pre>
  
  <p>Two issues here.</p>
  
  <ol>
  <li><p>I never receive any response regarding the second device (Bedroom Light), this is the message that is sent second. It seems that the send is being blocked, how would you recommend I format my sending so that I send after the response is received for the first send? There is only 1 COM port that can be used to send/receive. I believe I should Send message to Device 1, receive Device 1 response, Send to Device 2, receive Device 2. Could I end up seeing a huge traffic jam with a lot of devices and using wait conditions, ie. wait for device 1 communication process to finish before executing comm process for device 2?</p></li>
  <li><p>The very first read contains the appropriate 1st half of the receive. <code>Read:  "026220cbcf05190006"</code> The second receive contains the 2nd half of the 1st response followed by the 1st half of the second response: Read 2 - <code>Read:  "025020cbcf1edaf721000002621de94b05190006"</code> The appropriate full response is <code>02621DE94B05190006 025020CBCF1EDAF72100FF</code>
  (note <code>20CBCF</code> is Device 2's ID in the full response example)</p></li>
  </ol>
  
  <p>What corrections should be made to the way I am receiving data from the serial port?
  Thank you!</p>