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"); return; } if(!(connected = device->open(QIODevice::ReadWrite /*| QIODevice::Unbuffered*/))) { qWarning(Logging::thermometer) << "Serial port error:" << device->errorString(); return; }; 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..."); }); device->setBaudRate(115000); sendStartup(); }
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)); #else sendCommand(QByteArray(1,commandHeader).append("\x00", 1)); #endif #if QT_VERSION >= QT_VERSION_CHECK(5, 7, 0) emit nextCommand(QByteArray(1, command).append(1, page)); #else char c{static_cast<char>(page)}; emit nextCommand(QByteArray(1, command).append(&c, 1)); #endif
-
Hi,
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)
-
- 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.
- Why do you think QByteArray::append is different in the same Qt major version? I really doubt that.
-
- Will definitely consider the upgrade. As this is my home "hobby" work, it may take some time however.
- 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).
-
-
@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...
-
@aha_1980 Thank you so much for your ideas. Both problems solved.
-
After reconfiguring aptitude stuff to use "stable" instead of hard-coded "jessie" and half-a-day-long upgrades and cleaning the mess I really got not only higher version of Qt, but as well QParallelPort working as planned. Definitely worth the effort (even if I did not expect the upgrade to take so much time.)
-
My mistake. I missed this single character overload to append(). Thank you for pointing me there. Now I got completely rid of that development/release conditionals.
Case closed, thanks to all who assisted.
-