0

I'm trying to send some data over serial port using QSerialPort class. Sending data from the same parent class every time works well. But when I'm trying to send data using another thread QSerialPort it doesn't. I used serial port monitor to watch the data and it showed nothing. Code is looks like this:

#include <QSerialPort>
#include <QObject>
#include <QDebug>
#include <QCoreApplication>

#include <thread>
#include <mutex>
#include <list>
#include <memory>

class Message {
public:
    bool isSent;
    bool isProcessed;
    int data;

    Message(int d) :
        data(d),
        isSent(false),
        isProcessed(false) {

    }
};

class SerialClass : public QObject {
    Q_OBJECT

public:
    SerialClass(unsigned short portNumber, unsigned int baudrate, QObject *parent = 0) :
        _portNumber(portNumber),
        _baudrate(baudrate),
        _serialPort(new QSerialPort(this)),
        _messages(),
        _writeThread(nullptr),
        QObject(parent) {

        _serialPort->setPortName(QString("COM%1").arg(_portNumber));
        _serialPort->setBaudRate(baudrate);
        _serialPort->setDataBits(QSerialPort::DataBits::Data8);
        _serialPort->setParity(QSerialPort::Parity::NoParity);
        _serialPort->setStopBits(QSerialPort::StopBits::OneStop);
    }


    void start() {

        if (!_serialPort->open(QIODevice::ReadWrite)) {
            qDebug() << "Couldn't open serial port";
            return;
        }

        auto *m = &_messages;
        auto *p = &_enableProcessing;
        auto *port = _serialPort.get();
        auto *mutex = &_mutex;

        _serialPort->write(QString("Hello\r\n").toLocal8Bit());

        _writeThread = std::make_unique<std::thread>([m, p, port, mutex]() {
            qDebug() << "Work thread started";
            while (*p) {
                std::this_thread::sleep_for(std::chrono::milliseconds(15));
                auto inactiveMessage = std::find_if(m->begin(), m->end(), [](Message &item) {
                    return !item.isSent;
                });

                if (inactiveMessage != m->end()) {
                    mutex->lock();
                    qDebug() << "Written" << port->write(QString("data %1\r\n").arg(inactiveMessage->data).toLocal8Bit());
                    inactiveMessage->isSent = true;
                    mutex->unlock();
                }
            }
            qDebug() << "Work thread stopped";
        }); 
    }

    void wait() {
        if (!_writeThread) {
            return;
        }
        _writeThread->join();
    }


    void addMessage(Message& msg) {
        _mutex.lock();
        _messages.push_back(msg);
        _mutex.unlock();
    }

private:
    unsigned short _portNumber;
    unsigned int _baudrate;
    std::unique_ptr<QSerialPort> _serialPort;
    std::unique_ptr<std::thread> _writeThread;
    std::list<Message> _messages;
    bool _enableProcessing;
    std::mutex _mutex;
};


int main(int argc, char ** argv) {
    QCoreApplication application(argc, argv);
    SerialClass serialProcessor(2, 9600, &application);

    serialProcessor.addMessage(Message(228));
    serialProcessor.addMessage(Message(929));
    serialProcessor.addMessage(Message(221424));

    serialProcessor.start();

    return application.exec();
}

#include "main.moc"

Does it means what the QSerialPort class can not transmit data from another thread? (not QSerialPort thread)

1 Answers1

0
  1. It is recommended not to mix STL and Qt solutions in the same project
  2. QSerialPort can work in any thread
  3. You can see an example of correct using of QThread here: https://stackoverflow.com/a/35673612/4149835
Community
  • 1
  • 1
Vladimir Bershov
  • 2,701
  • 2
  • 21
  • 51