My program alerts the user when something has happened. To get his attention, a alert sound plays. It stops when the user enter something to confirm receipt.
But the QTextStream input blocks the sound !
When I remove it, the sound plays perfectly.
Besides, the "alert" QSound object doesn't work. The only way to play is to use the static function QSound::play("file.wav"). But it can't be stopped.
Here is my code :
#include <QCoreApplication>
#include <QSound>
#include <QDebug>
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
/*
QSound alert("../SoundAlerte/alert.wav");
alert.setLoops(QSound::Infinite);
alert.play();
*/
QSound::play("../SoundAlerte/alert.wav");
qDebug() << "ALERT";
qDebug() << "Enter Something to confirm receipt" ;
QTextStream s(stdin);
QString value = s.readLine();
qDebug() << "Received !";
//alert.stop();
qDebug() << "Sound stopped";
return a.exec();
}
It seems like it can't play a sound and wait for input at the same time !
Do you have have an idea on how to proceed ?
Thanks
QSound::play is asynchron, but
QString value = s.readLine();
contains a do-while and will block the audio file. See scan function called by readLine()
A working example would be QtConcurrent, but you can't stop the audio file, so you might want to switch to a real QThread approach.
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
QFuture<void> future = QtConcurrent::run([]() {
QSoundEffect effect;
QEventLoop loop;
effect.setSource(QUrl::fromLocalFile("C:\\piano2.wav"));
effect.setVolume(0.25f);
effect.play();
QObject::connect(&effect, &QSoundEffect::playingChanged, [&loop]() { qDebug() << "finished"; loop.exit(); });
loop.exec();
});
QTextStream s(stdin);
QString value = s.readLine();
return a.exec();
}
Related
I'm trying to get global position of the mouse however the functions mentioned in older topics are either deprecated or not working as intended. I have tried QCursor::pos() as seen below but it didn't work as intended.
#include <QtCore/QCoreApplication>
#include <QCursor>
#include <iostream>
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
while(1)
{
std::cout << QCursor::pos().x() << " " << QCursor::pos().y() << std::endl;
}
return a.exec();
}
Output: 2147483647 2147483647
It is very simple. QCursor is in the Gui module of Qt see here, so you have to change QCoreApplication to QGuiApplication and then it works (already tested it).
That is how i tried it at first but i get an error "no operator found that takes a left hand operand of type 'QTextStream' or there is no acceptable conversion"
QList<QString>lNamesList;
void write(){
QFile data("E:/Test/output.h");
if (data.open(QFile::WriteOnly))
{
QTextStream out (&data);
nameList.append("Name1");
out << NameList;
}
}
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
write();
return a.exec();
}
You cannot feed your nameList directly to your QTextStream. You can give it a string or QString. So you might want to loop over your QList which would look something like this:
for(const QString& str : nameList){
out << str;
}
note: see the docs for more info
I have been struggling for an embarrassingly long time now to correctly read Umlaute from a Windows encoded file. The file is saved using the Windows-1252 codec and consists of one single line:
123 äöü 456
My simple test program to isolate the behavior I don't understand is;
#include <QCoreApplication>
#include <QDebug>
#include <QFile>
#include <QTextCodec>
#include <QByteArray>
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
QStringList ids;
QFile inputFile("test.txt");
QTextCodec *codec = QTextCodec::codecForName("Windows-1252");
if (inputFile.open(QIODevice::ReadOnly))
{
QTextStream in(&inputFile);
while (!in.atEnd())
{
QByteArray line = inputFile.readLine();
QString string = codec->toUnicode(line);
qDebug() << string;
}
inputFile.close();
}
else
qDebug() << "Cannot open file";
return a.exec();
}
The console output is:
"123 ??? 456\r\n"
So all the Umlaute get eaten up.
I am running this in Linux, the terminal emulator is set to use UTF-8. What can possibly go wrong here.
I am trying to transfer data from Arduino to a C++ Qt5.7 and from a Arduino to a C++ Qt5.7 (MinGW) program.
I am able to transfer the data FROM QT TO ARDUINO without any problems.
The Arduino blinks perfectly.
On the other hand, the data transfered FROM THE ARDUINO TO QT isnt always the expected (sends "LED ON" when it should be "LED OFF") and sometimes it doesnt communicate at all!
QT code:
#include <QCoreApplication>
#include <QDebug>
#include <QSerialPort>
#include <QSerialPortInfo>
#include <QThread>
#include <iostream>
using namespace std;
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
QSerialPort serial;
serial.setPortName("COM6");
serial.setBaudRate(9600);
serial.setDataBits(QSerialPort::Data8);
serial.setParity(QSerialPort::NoParity);
serial.setStopBits(QSerialPort::OneStop);
serial.setFlowControl(QSerialPort::NoFlowControl);
if(serial.open(QSerialPort::ReadWrite))
{
string c;
QByteArray s;
QByteArray received;
while(true)
{
qDebug("TRUE");
//WRITE
cin >> c;
cout << endl;
s = QByteArray::fromStdString(c);
serial.write(s);
serial.waitForBytesWritten(-1);
//serial.flush();
s = serial.readAll();
serial.waitForReadyRead(-1);
cout << s.toStdString() << endl;
//serial.flush();
}
}
else
{
QString error = serial.errorString();
cout << error.toStdString() << endl;
qDebug("FALSE") ;
}
serial.close();
return a.exec();
}
The ARDUINO CODE:
void setup() {
// initialize digital pin LED_BUILTIN as an output.
pinMode(LED_BUILTIN, OUTPUT);
Serial.begin(9600);
}
// the loop function runs over and over again forever
void loop() {
delay(1000); // wait for a second
}
void serialEvent()
{
char inChar;
while (Serial.available())
{
// get the new byte:
inChar = (char)Serial.read();
if(inChar == 'a')
{
digitalWrite(LED_BUILTIN, HIGH); // turn the LED on (HIGH is the voltage level)
}
else
{
digitalWrite(LED_BUILTIN, LOW); // turn the LED off (LOW is the voltage level)
}
}
delay(500);
if(inChar == 'a')
{
Serial.write("LED ON");
}
else
{
Serial.write("LED OFF");
}
}
Terminal Image of Error:
TERMINAL WITH ERROR image
Please help!
Thank you,
You have no packetization whatsoever: there are no delimiters between individual chunks of data - other than time passing.
On the Arudino side, instead of write, you should use println so that each message is a complete line.
On the Qt side, process complete lines. You're not guaranteed to get a complete response from the serial port after waitForReadyRead. All that you're guaranteed is that at least 1 byte is available to read. That is the source of your problem. Note how you got LE, then sometime later you got D OFF immediately followed by LED ON. You must wait for data until complete line(s) are available.
The following should work on the Qt end of things - also note that you don't need as many includes, and you can use QTextStream instead of iostream, to lower the number of APIs that you use. Finally, you don't need app.exec since you write blocking code.
// https://github.com/KubaO/stackoverflown/tree/master/questions/arduino-read-40246601
#include <QtSerialPort>
#include <cstdio>
int main(int argc, char *argv[])
{
QCoreApplication a{argc, argv};
QTextStream in{stdin};
QTextStream out{stdout};
QSerialPort port;
port.setPortName("COM6");
port.setBaudRate(9600);
port.setDataBits(QSerialPort::Data8);
port.setParity(QSerialPort::NoParity);
port.setStopBits(QSerialPort::OneStop);
port.setFlowControl(QSerialPort::NoFlowControl);
if (!port.open(QSerialPort::ReadWrite)) {
out << "Error opening serial port: " << port.errorString() << endl;
return 1;
}
while(true)
{
out << "> ";
auto cmd = in.readLine().toLatin1();
if (cmd.length() < 1)
continue;
port.write(cmd);
while (!port.canReadLine())
port.waitForReadyRead(-1);
while (port.canReadLine())
out << "< " << port.readLine(); // lines are already terminated
}
}
If you wish, you can also easily turn it into a GUI application, it's only a few lines to do so:
#include <QtSerialPort>
#include <QtWidgets>
int main(int argc, char *argv[])
{
QApplication app{argc, argv};
QWidget ui;
QFormLayout layout{&ui};
QLineEdit portName{"COM6"};
QTextBrowser term;
QLineEdit command;
QPushButton open{"Open"};
layout.addRow("Port", &portName);
layout.addRow(&term);
layout.addRow("Command:", &command);
layout.addRow(&open);
ui.show();
QSerialPort port;
port.setBaudRate(9600);
port.setDataBits(QSerialPort::Data8);
port.setParity(QSerialPort::NoParity);
port.setStopBits(QSerialPort::OneStop);
port.setFlowControl(QSerialPort::NoFlowControl);
QObject::connect(&open, &QPushButton::clicked, &port, [&]{
port.setPortName(portName.text());
if (port.open(QSerialPort::ReadWrite)) return;
term.append(QStringLiteral("* Error opening serial port: %1").arg(port.errorString()));
});
QObject::connect(&command, &QLineEdit::returnPressed, &port, [&]{
term.append(QStringLiteral("> %1").arg(command.text()));
port.write(command.text().toLatin1());
});
QObject::connect(&port, &QIODevice::readyRead, &term, [&]{
if (!port.canReadLine()) return;
while (port.canReadLine())
term.append(QStringLiteral("< %1").arg(QString::fromLatin1(port.readLine())));
});
return app.exec();
}
I think you must use EOL and Carrige return character on QT. Try to replace Serial.write to Serial.println in Arduino code.
I am trying to rig up some basic serial communications in QT
I am getting the port COM19 from QSerialPortInfo, and I speaking successfully to the port via Arduino. However, I cannot get anything back via QT.
#include "mainwindow.h"
#include <QApplication>
#include <QDebug>
#include <QTextStream>
#include <QFile>
#include <QtSerialPort/QSerialPort>
#include <QtSerialPort/QSerialPortInfo>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
foreach(const QSerialPortInfo &info, QSerialPortInfo::availablePorts()){
qDebug() << "Name :" << info.portName();
qDebug() << "Description :" << info.description();
qDebug() << "Manufactuer :" << info.manufacturer();
QSerialPort serial;
serial.setPort(info);
if(serial.open(QIODevice::ReadWrite))
qDebug() << serial.errorString();
serial.write("M114 \n");
qDebug() << serial.readAll();
serial.close();
// Now we need to send and receive commands
serial.setPortName("COM19");
serial.setBaudRate(QSerialPort::Baud57600);
serial.setDataBits(QSerialPort::Data8);
serial.setParity(QSerialPort::NoParity);
serial.setStopBits(QSerialPort::OneStop);
serial.setFlowControl(QSerialPort::NoFlowControl);
if(serial.open(QIODevice::ReadWrite)){
qDebug() << "opened";
}else{
qDebug() << "Not opened";
}
qDebug() << serial.errorString();
serial.write("M114 \n");
qDebug() << serial.readAll();
serial.close();
}
MainWindow w;
w.show();
return a.exec();
}
As you can see, I am trying a simple connection along the lines of the documentation, and one where I write out all the baud rate information. They throw two different errors.
Like I said, I am connecting via arduino to this same port and having success. Any ideas what's wrong?
Name : "COM19"
Description : "USB Serial (Communication Class, Abstract Control Model)"
Manufactuer : "PJRC.COM, LLC."
"Unknown error"
""
opened
"The handle is invalid."
""
Any ideas for what I am doing wrong?
My idea is to send commands to the device, and read them back to the console.
the code looks a bit confuse. You open all port available and then you try to do something wrong.
NOTE: You use a GUI application like a shell application. It is wrong.
Try:
#include "mainwindow.h"
#include <QApplication>
#include <QDebug>
#include <QTextStream>
#include <QFile>
#include <QtSerialPort/QSerialPort>
#include <QtSerialPort/QSerialPortInfo>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QSerialPort serial;
serial.setPortName("COM19");
if(serial.open(QIODevice::ReadWrite)){
//Now the serial port is open try to set configuration
if(!serial.setBaudRate(QSerialPort::Baud57600))
qDebug()<<serial.errorString();
if(!serial.setDataBits(QSerialPort::Data8))
qDebug()<<serial.errorString();
if(!serial.setParity(QSerialPort::NoParity))
qDebug()<<serial.errorString();
if(!serial.setStopBits(QSerialPort::OneStop))
qDebug()<<serial.errorString();
if(!serial.setFlowControl(QSerialPort::NoFlowControl))
qDebug()<<serial.errorString();
//If any error was returned the serial il corrctly configured
serial.write("M114 \n");
//the serial must remain opened
if(serial.waitForReadyRead(100)){
//Data was returned
qDebug()<<"Response: "<<serial.readAll();
}else{
//No data
qDebug()<<"Time out";
}
//I have finish alla operation
serial.close();
}else{
qDebug()<<"Serial COM19 not opened. Error: "<<serial.errorString();
}
MainWindow w;
w.show();
return a.exec();
}
Starting with the tenth port, his name will be \\.\COM10
You can reassign the port to a different number in Device Manager