c++qtserial-portqbytearray

How can I iterate through bytes in a QByteArray individually?


I have a custom signal-slot in Qt C++ in which I want to store data received from a serial port (QSerialPort) to show data from 25 different sensors I have on an embedded system. Values for my sensors range from 5900 to 7200, so I wanted to send a different letter as a char (ranging from a to y, 25 letters) between each sensor value, so my Qt program can tell which sensor data is received next, followed with a stop byte which would be universal for my 25 sensors.

void MainWindow::serialReceived()   // runs individually for almost every byte
{
    QByteArray ba = serial->readAll();
    qDebug() << ba.size();
}

for now, I am using the readAll() function, and most of the time this slot function (serialReceived() ) is called often enough so that only 1 char is received at a time, so I can check for the letter identifying the sensor, then at the next function call I can check the leftmost number of the sensor data, etc until I reach the 4th number and then the stop byte, before the process is repeated.

The problem is sometimes it receives more than a byte at once, so if there are more than one values in my ba, I do not know what would be a good way to check for the individual bytes received (ex: did I receive a letter, followed by the 2 first numbers of the next sensor value??).

This is what I managed to do so far, but it doesnt work since I get a problem as soon as I read more than 1 byte at once in my slot function:

void MainWindow::serialReceived()   // runs individually for almost every byte
{
    static char stepFlag = 0;

    QByteArray ba = serial->readAll();
    qDebug() << ba.size(); //receives 1 byte and

    QString s;
    s = QString::number(stepFlag), qDebug() <<"step: "<< s;
    qDebug() <<"ba: " << ba;
    if (ba == "<") stepFlag = 1, s = QString::number(stepFlag), qDebug() << s;
    s = QString::number(currentSensorValue), qDebug() << s;

    switch (stepFlag) {
    case 0:
        qDebug() << "starts";
            if (ba == "<")
                stepFlag = 1;
    break;

    case 1:
        ID = ba.toInt();
        qDebug() << ID;
        stepFlag = 2;
    break;

    case 2:
        stepFlag++;
        currentSensorValue = ba.toInt()*1000; // first char is the 1st number of data (representing thousands)
    break;

    case 3:
        stepFlag++;
        currentSensorValue += ba.toInt()*100;
    break;

    case 4:
        stepFlag++;
        currentSensorValue += ba.toInt()*10;
    break;

    case 5:
        stepFlag++;
        currentSensorValue += ba.toInt();
    break;

    case 6:
        //qDebug() << "a" << currentSensorValue;

        if (ba.toInt() == 'r')
        {
        switch (ID)
        {
        case 'a':
        ui->RX0TX0_LCD->display(currentSensorValue);
        qDebug() << "a" << currentSensorValue;
        break;

        case 'b':
        qDebug() << "b" << currentSensorValue;
        break;

        //This switch would go on for all of the 25 letters (sensors)

        default:
        break;
        }
        ID = 0;
        }

        if (ba.toInt() == 'n')
           {
            stepFlag = 0;
           }
    break;

    default:
    break;
    }
    }

So basically my problem is how can I read 1 byte at a time from the QserialPort so this problem does not occur anymore? I am also unsure of if my method for receiving chars is very efficient. Thank you!


Solution

  • You can iterate each single byte through a QByteArray as:

    QByteArray::iterator iteratorByte;
    int count = 0;
    for (iteratorByte = ba.begin(); iteratorByte != ba.end() ; iteratorByte++ ) {
        QByteArray test1Byte(1,0); //Define a 1 Byte fixed length variable
        test1Byte[0]= ba.at(count++); //Assign each byte of the QByteArray ba to this variable
        qDebug() << test1Byte.toHex(); //Print that 1 Byte in hex format
    }