Selecting from all available serial ports using Qt GUI - c++

I could not find a conclusive answer to my issue so I decided to post my first question on this site. I'm fairly new to programming and have been using Qt for a couple of months now.
My code communicates with a microcontroller via serial ports, however the available port differs from pc to pc. I'm displaying the number of ports available with the code;
qDebug() << "Number of serial ports:" << QSerialPortInfo::availablePorts().count();
My question is: how can I display the name of all the available ports eg "COM 10, 17. 22, etc" and then show them in my GUI. What I eventually hope to do is have a combo box that can be dynamically populated with the available ports, I have one that switches between a couple ports at the moment but these are fixed ports corresponding to particular computers.

Try something like this:
#include <QApplication>
#include <QWindow>
#include <QSerialPortInfo>
#include <QComboBox>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QWidget w;
w.resize(200,200);
w.show();
QComboBox box(&w);
Q_FOREACH(QSerialPortInfo port, QSerialPortInfo::availablePorts()) {
box.addItem(port.portName());
}
box.move(100 - box.width() / 2,100 - box.height() / 2);
box.show();
return a.exec();
}
The code is pretty self-explanatory.

Found a relevant answer on qt centre, example code;
foreach (const QSerialPortInfo &serialPortInfo, QSerialPortInfo::availablePorts())
{
ui->comboBox->addItem(serialPortInfo.portName());
}

Related

Modbusclient as a console application, "Stuck in Connectingstate loop"

I'm trying hardly to convert the Modbusmaster example (qt example) which is a widget application to a console application. I wanted to build a connection between a local slave and my master. The problem I'm facing is that my code is changing its state to “Connecting state” ,gets stuck and doesn't want to build a connection. That's why, I recon that the Modbus library is limited and it's only compatible with the widget form.
Could someone tell me if my guesses are right.
down below you will find my code:
#include <QCoreApplication>
#include <QDebug>
#include <QModbusDataUnit>
#include<iostream>
#include <QTimer>// this bib was add to the 50ms Loop check
#include <string>
#include <QString>
#include <QThread>
#include <QModbusTcpClient>
#include <QModbusDataUnit>
#include <QUrl>
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
Mainmodbus T ;
T.modbusDevice = new QModbusTcpClient();
if (!T.modbusDevice) qDebug()<<"error 1";
if (T.modbusDevice->state() != QModbusDevice::ConnectedState) {
T.modbusDevice->setConnectionParameter(QModbusDevice::NetworkAddressParameter, "127.0.0.1");
T.modbusDevice->setConnectionParameter(QModbusDevice::NetworkPortParameter, 502);
T.modbusDevice->connectDevice();
while(true){
qDebug()<<T.modbusDevice->state();}
}
return a.exec();
}
I can be wrong but I think the QModbusDevice::ConnectingState you see actually means your server is up and running and waiting for a connection.
I guess what you are missing is opening a connection from a Modbus client. You can do that with different tools, I guess running the client example
would be a good idea. Otherwise, you can use QModMaster or any other tool you like.
Once you open the connection from the client the state on your server should change to QModbusDevice::ConnectedState.
Be aware that the server you built is just an empty shell, there is no register map defined so if you query the contents of any register from the client you will get an error.
At the very minimum, you should at least define a map with some default values or get them from command-line options. To do that you need to look at the server example a bit more carefully.
First you need to define the register map with something like this:
QModbusDataUnitMap reg;
reg.insert(QModbusDataUnit::Coils, { QModbusDataUnit::Coils, 0, 10 });
reg.insert(QModbusDataUnit::DiscreteInputs, { QModbusDataUnit::DiscreteInputs, 0, 10 });
reg.insert(QModbusDataUnit::InputRegisters, { QModbusDataUnit::InputRegisters, 0, 10 });
reg.insert(QModbusDataUnit::HoldingRegisters, { QModbusDataUnit::HoldingRegisters, 0, 10 });
modbusDevice->setMap(reg);
setupDeviceData();
And then for the setupDeviceData(); you can copy the function in the example but instead of taking the data from the widget, you will have to load default values or something from the command line.
In answer to your question: no, there should be no limitation and you should be able to run the server from the command line. I wonder why somebody on his/her right mind would want to do that when you have excellent alternatives like libmodbus. But honestly, I won't miss much sleep wondering.

Can input audio be processed by more apps at once with Qt?

I would like to use the QAudioRecorder to record audio from microphone. My question is, should there be an ongoing Skype call or another application would try to use the microphone, would this result in some error or would both that app and my app receive same audio input data?
Similarly, can I use the QCamera and QMediaRecorder to access webcam that is being used already?
Yes, that will work just fine, there won't be any error. Both applications will receive the same audio input data. I tested to record the same thing at the same time using Windows' voice recorder program and a simple Qt program built with the following code, and the result was that both output files were recorded the sound correctly:
#include <QApplication>
#include <QAudioRecorder>
#include <QPushButton>
#include <QUrl>
int main(int argc, char **argv){
QApplication app(argc, argv);
QAudioRecorder *audioRecorder = new QAudioRecorder;
QAudioEncoderSettings audioSettings;
audioSettings.setCodec("audio/amr");
audioSettings.setQuality(QMultimedia::HighQuality);
audioRecorder->setEncodingSettings(audioSettings);
audioRecorder->setOutputLocation(QUrl::fromLocalFile("C:\\Users\\dduck\\Desktop\\test.amr"));
QPushButton b("Start");
QObject::connect(&b, &QPushButton::clicked, [&](){
if(b.text() == "Start"){
audioRecorder->record();
b.setText("Stop");
}
else{
audioRecorder->stop();
app.quit();
}
});
b.show();
return app.exec();
}
I assume it would also work if you run that program at the same time as Skype.
So yes, input audio can be processed by a Qt program at the same time as it is processed by other programs.

Problems Receiving QSerialPort Signals

I'm trying to write a simple program to test out the serial port, but am having trouble getting QSerialPort to work. I never receive signals from the QSerialPort object. I get 3 runtime warnings/errors that I think probably have something to do with it.
The errors are:
QApplication::qAppName: Please instantiate the Qapplication object first
QSocketNotifier: Can only be used with threads started with QThread
QSocketNotifier: Can only be used with threads started with QThread
The code snippet below is the smallest sample I can give to recreate the errors, it doesn't show me connecting signals but I think these errors are why I don't see them. If I don't call the open function none of the errors occur.
#include <QtGui/QApplication>
#include <QSerialPort>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
PowerBoardGUI w;
w.show();
QSerialPort* serial = new QSerialPort();
serial->setPortName("/dev/ttyS1");
serial->setBaudRate(QSerialPort::Baud9600);
bool isOpen = serial->open(QIODevice::ReadWrite);
serial->close();
delete serial;
return a.exec();
}
The test system is Redhat 5.6. A static version of QT 4.7.4. And the latest version of QSerialPort (built from GIT today).

parallely run an application while it starts another application in c++

I am trying to write an application program that can start another application using c++ in linux . Starting another application is not the problem . The problem I am facing is, that the parent application pauses till the child application is closed. I want the parent application to run along with the child application so that more functionalities of the parent application can be used. How do i go about it?
It would help me a lot if somebody could give me an idea on this.
The application consists of two files main.cpp and a virtualbotmain.cpp. The part of the
virtualbotmain.cpp: #include <iostream>
#include <stdlib.h>
VirtualBotMain::VirtualBotMain(QWidget *parent) :
QWidget(parent),
ui(new Ui::VirtualBotMain)
{
ui->setupUi(this);
}
void VirtualBotMain::on_enterButton_clicked()
{
QString enterString = ui->enterEdit->text();
ui->convoText->append("User: " + enterString);
ui->enterEdit->setText("");
if(enterString=="word")
{
ui->convoText->append("Joe: done..!!");
system("gedit");
}
}
The main.cpp is :
#include <QtGui/QApplication>
#include "virtualbotmain.h"
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
VirtualBotMain w;
w.show();
return a.exec();
}
This is a GUI application that can be used to just type in the application i am trying to open and the application will do it for me. So trying to open many applications one after the other is becoming a problem as the GUI application won't work untill i close the previously opened application.
If you're using a system call (or a similar way to invoke the shell), you can apply the same logic you'd apply in your terminal to start a process "in the background":
system("./myProgram &");
// ^
// run in background
Better alternatives include forking, though it really depends on your specific requirements, which we do not know.
#include <stddef.h>
#include <process.h>
int status = spawnl( P_NOWAIT, "myprog", "myprog", "ARG1", "ARG2", NULL );

Simplest Qt Dialog

I have a C++ function that checks if Bluetooth is activated. I want to display a simple dialog telling the user to activate his Bluetooth and try again. As I have a QML interface this can be done through C++ or QML.
You can use the built-in information message box:
#include <QApplication>
#include <QDebug>
#include <QMessageBox>
int main(int argc, char *argv[]) {
QApplication app(argc, argv);
QMessageBox::information(0, "Try Again", "Please try to activate your Bluetooth again.");
}
Qt Components have some dialogs out of box:
http://doc.qt.nokia.com/qt-components-symbian-1.0/qml-querydialog.html