QSerialPort::readyRead() seems not get emitted on one installation while on other works normally

  • I am developing heating controller app using Elitech RC-5 thermometer for feedback. It communicates via the USB port, driven by /dev/ttyUSB0. Everything works fine on my production desktop, where I developed the app.

    ii  qt5-qmake:amd64                   5.9.1+dfsg-9          amd64
    ii  g++                               4:7.2.0-1d1           amd64
    Linux 4.13.0-1-amd64 #1 SMP Debian 4.13.4-2 (2017-10-15) x86_64 GNU/Linux

    When I compile the same code (except of small adaptations for older Qt version shown below) on my server (where it should run finally)

    ii  qt5-qmake:amd64                   5.3.2+dfsg-4+deb8u2   amd64
    ii  g++                               4:4.9.2-2             amd64 
    Linux 3.16.0-4-amd64 #1 SMP Debian 3.16.43-2+deb8u5 (2017-09-19) x86_64 GNU/Linux

    the slot connected to QSerialPort::readyRead() gets never called. Snooping with tshark shows, that not only the proper request is sent, but even the proper response is received. So the problem must lay somewhere in between the device driver and the Qt library. I spent several days trying and googling and finally found the important difference. In the following part of code called from ThermometerRc5 constructor if I uncomment the QIODevice::Unbuffered part

    void ThermometerRc5::restart()
        if(!device.isNull()) device->close();
    	lastCommand = 0;
    	samplingTimer.start(Thermometry::samplingPeriod, this);
        qDebug(Logging::thermometer)		<< "USB devices available:";
    	foreach(QSerialPortInfo info, QSerialPortInfo::availablePorts()) {
    	// Rather hardcoded here, than passed as device name parameter.
    	// This concept SHOULD CHANGE if more than one thermometer will have to be utilised.
    		bool selected{(info.vendorIdentifier() == 6790) && (info.productIdentifier() == 29987)};
    		qDebug(Logging::thermometer)		<< (selected ? "----> " : "")
        				<< info.portName() << "="
    	    			<< info.description();
    		if(selected) device.reset(new QSerialPort(info));
    	if(device.isNull()) {
        	qWarning(Logging::thermometer) << tr("No thermometer device found");
    	if(!(connected = device->open(QIODevice::ReadWrite /*| QIODevice::Unbuffered*/))) {
        	qWarning(Logging::thermometer) << "Serial port error:" << device->errorString();
    	qDebug(Logging::thermometer) << tr("device:") << device.data() << connected;
    	connect(device.data(), &QIODevice::readyRead, this, &ThermometerRc5::onReadyRead, static_cast<enum Qt::ConnectionType>(Qt::AutoConnection | Qt::UniqueConnection));
    	connect(device.data(), &QIODevice::readyRead, [this](){
    	qDebug(Logging::thermometer) << tr("SUCCESS!!! QIODevice::readyRead() called...");

    I get error

    thermometer: Serial port error: "No such file or directory"

    which does not appear without this QIODevice::Unbuffered flag, however in that case not even the lambda connected to readyRead() signal gets called...

    On the production desktop with QIODevice::Unbuffered flag I am instead getting

    thermometer: Serial port error: "Unsupported open mode"

    I am giving up and calling for some expert Qt gurus to recommend further tests or code workarounds...

    Thanks in advance for any clues.

    The relevant code snippets follows:

    Addaptations between Qt versions (for completeness; none should interfere with serial communication)

    lessThan(QT_MINOR_VERSION,5) {
        message(QT version less than latest: $$QT_VERSION)
        DEFINES += \"qDebug(x)\"=\"*console\"
        DEFINES += \"qInfo(x)\"=\"*console\"
        DEFINES += \"qWarning(x)\"=\"*console\"
        DEFINES += \"toHex(x)\"=\"toHex()\"
    #if QT_VERSION >= QT_VERSION_CHECK(5, 7, 0)
    		sendCommand(QByteArray(1,commandHeader).append(1, 0x00));
    		sendCommand(QByteArray(1,commandHeader).append("\x00", 1));
    #if QT_VERSION >= QT_VERSION_CHECK(5, 7, 0)
    	emit nextCommand(QByteArray(1, command).append(1, page));
    char c{static_cast<char>(page)};
    	emit nextCommand(QByteArray(1, command).append(&c, 1));

  • Lifetime Qt Champion


    Might be a silly question but, did you check that the user of that system has access to the serial port device ? (i.e. is member of the group having access to it)

  • @pmendl:

    1. Please consider upgrading Qt on the server. 5.3 is no longer supported and serialport was quite new than. Its possible that it contained a bug.
    2. Why do you think QByteArray::append is different in the same Qt major version? I really doubt that.

  • @aha_1980

    1. Will definitely consider the upgrade. As this is my home "hobby" work, it may take some time however.
    2. Found that as I got getting error messages about constructor signature. Seems like constructor filling multiple copies of some integer into QByteArray is not present in Qt 5.3 headers (however eventually some Debian dev package could not be installed correctly - I did installation through "main" Qt5 package found via aptitude).

  • @SGaist Not sure (even if I guess so) if I checked explicitely, however if no privilege missing messages produced on device opening and wireshark shows (correct) USB package transmission going both directions this is the unlikely cause.

  • Qt Champions 2016

    Have you checked with another serial port program ( like minicom)
    if that can read anything ?

  • @pmendl: If I get it correctly, all you want to do is appending a character to the array. Therefore you can use the append(char) overload, that already existed in Qt 4.8: http://doc.qt.io/qt-4.8/qbytearray.html#append-5

    This will make your code cleaner and easier to debug.

    And really, really update to a newer Qt. I would not recommend it if everything worked fine, but as you already have problems that don't appear with the newer version...

Log in to reply

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.