How can I use Qt for creating bluetooth applications? - c++

I'm new to Qt framework. This is my first C++ implementation in real world applications. I was facing problem in preparing this bluetooth based application. I went through Qt documentation too, but it didn't work. Code is :
CLASS HEADER
#ifndef MAINCLASS_H
#define MAINCLASS_H
#include <QObject>
#include <QBluetoothServiceDiscoveryAgent>
#include <QBluetoothServiceInfo>
#include <QBluetoothLocalDevice>
class MainClass : public QObject
{
Q_OBJECT
public:
explicit MainClass(QObject *parent = 0);
~MainClass();
void startDiscovery(void);
signals:
public slots:
void onDiscovery(const QBluetoothServiceInfo &serviceInfo);
private:
QBluetoothServiceDiscoveryAgent *discoveryAgent;
QBluetoothLocalDevice *bluetoothDevice;
};
#endif // MAINCLASS_H
// MEMBER DEFINITIONS
#include "mainclass.h"
#include <QDebug>
MainClass::MainClass(QObject *parent) : QObject(parent)
{
bluetoothDevice = new QBluetoothLocalDevice();
QBluetoothAddress bluetoothAddress = bluetoothDevice->address();
discoveryAgent = new QBluetoothServiceDiscoveryAgent(bluetoothAddress);
connect(discoveryAgent, SIGNAL(serviceDiscovered(QBluetoothServiceInfo)),
this, SLOT(onDiscovery(QBluetoothServiceInfo)));
discoveryAgent->setUuidFilter(QBluetoothUuid(QBluetoothUuid::ObexObjectPush));
discoveryAgent->start();
if(!discoveryAgent->isActive())
qDebug()<<"Not active";
if(discoveryAgent->error() != QBluetoothServiceDiscoveryAgent::NoError)
qDebug()<<discoveryAgent->errorString();
}
MainClass::~MainClass()
{
delete(discoveryAgent);
}
void MainClass::onDiscovery(const QBluetoothServiceInfo &serviceInfo)
{
qDebug() << "Discovered service on"
<< serviceInfo.device().name() << serviceInfo.device().address().toString();
qDebug() << "\tService name:" << serviceInfo.serviceName();
qDebug() << "\tDescription:"
<< serviceInfo.attribute(QBluetoothServiceInfo::ServiceDescription).toString();
qDebug() << "\tProvider:"
<< serviceInfo.attribute(QBluetoothServiceInfo::ServiceProvider).toString();
qDebug() << "\tL2CAP protocol service multiplexer:"
<< serviceInfo.protocolServiceMultiplexer();
qDebug() << "\tRFCOMM server channel:" << serviceInfo.serverChannel();
}
Main Function
#include "mainclass.h"
int main()
{
MainClass obj;
}
This piece of code wasn't showing lists of surrounding bluetooth devices. Any suggestions?

Related

Getting Exitcode from Powershell from within C++ Program with QProcess

I wonder if someone has an Answer for this Problem.
I use QProcess to start a Powershell script. The start of the QProcess is initiated from a QThread. This Thread finishes like expected but the QProcess never calls its readyReadStandardOutput() Signal nor its finished() Signal. Both are bound to 2 different slots and I can see that the script gets executed and I also know that the script finshes with an exitCode.
My goal with this is basically to read the Exitcode of the Powershell script I wrote. I tried different approaches but could not find a solution to get the Exitcode of the Powershell script which is either ran with cstdlib function system() or QProcess. So I decided I would read it from stdout. For that I would simply print the $LastExitCode before exiting the script and read that from within the C++ Program.
Thanks in advance.
Edit:
Updated example:
main.cpp
#include <QtCore/QCoreApplication>
#include <QTextStream>
#include "ManagerClass.h"
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
QTextStream wrappedStream(stdin);
QString scriptPath;
if (argc < 2)
{
std::cout << "Path to script:" << "\n";
wrappedStream >> scriptPath;
}
ManagerClass manager(scriptPath);
return a.exec();
}
ManagerClass.h
#pragma once
#include <QObject>
#include <QProcess>
#include <iostream>
#include "ExecutionThread.h"
class ManagerClass : public QObject
{
Q_OBJECT
public:
ManagerClass(const QString& p_scriptPath, QObject *parent = nullptr);
~ManagerClass();
public slots:
void threadFinished();
void processStarted();
void processFinished(int exitCode, QProcess::ExitStatus exitStatus);
private:
ExecutionThread m_thread;
const QString SCRIPT_PATH;
};
ManagerClass.cpp
#include "ManagerClass.h"
ManagerClass::ManagerClass(const QString& p_scriptPath, QObject* parent)
: QObject(parent), SCRIPT_PATH(p_scriptPath)
{
m_thread.getProcessPointer();
m_thread.registerScriptPath(p_scriptPath);
QObject::connect(m_thread.getProcessPointer(), QOverload<int, QProcess::ExitStatus> ::of(&QProcess::finished), this, &ManagerClass::processFinished);
QObject::connect(m_thread.getProcessPointer(), &QProcess::started, this, &ManagerClass::processStarted);
QObject::connect(&m_thread, &ExecutionThread::finished, this, &ManagerClass::threadFinished);
m_thread.start();
}
ManagerClass::~ManagerClass() {}
void ManagerClass::processFinished(int exitCode, QProcess::ExitStatus exitStatus)
{
std::cout << " Process finished successfully." << "\n";
std::cin.get();
}
void ManagerClass::threadFinished()
{
std::cout << " Thread finished successfully." << "\n";
}
void ManagerClass::processStarted()
{
std::cout << " Process started." << "\n";
}
ExecutionThread.h
#pragma once
#include <QThread>
#include <QProcess>
#include <iostream>
class ExecutionThread : public QThread
{
Q_OBJECT
public:
ExecutionThread();
~ExecutionThread();
void run();
void registerScriptPath(const QString& p_scriptPath);
QProcess* getProcessPointer();
signals:
void finished();
private:
QProcess* m_Process;
QString m_scriptPath;
};
ExecutionThread.cpp
#include "ExecutionThread.h"
ExecutionThread::ExecutionThread() : m_Process(new QProcess) {}
ExecutionThread::~ExecutionThread()
{
std::cout << "ExecutionThread::~ExecutionThread()";
}
void ExecutionThread::run()
{
QStringList commands;
m_Process->start(m_scriptPath, commands);
emit finished();
}
void ExecutionThread::registerScriptPath(const QString& p_scriptPath)
{
m_scriptPath = p_scriptPath;
}
QProcess* ExecutionThread::getProcessPointer()
{
return m_Process;
}
EDIT:
I solved the issue I was facing with always getting 1 as Exitcode.
It turns out that I misunderstood the Qt API for QProcess.
Still I dont get Signals from that QProcess object when it finishes.
The above Example uses m_Process->start() and there is no signal whenever the given powershell script finishes. As mentioned before m_Process->execute() doesnt signal anything too.

QProcess do not run an external application

I can run an external application using the following command:
system("/home/felippe/Área\\ de\\ Trabalho/Felippe/Mestrado/C_plus_plus/Codigos/build-Registration_ITK_CMAKE-Desktop_Qt_5_12_3_GCC_64bit-Default/Registration_ITK_CMAKE")
And the application runs successfully. But the system(.) command blocks the other commands until the application finishes. So I tried to implement this command in QT using the following code:
.h
#ifndef FOO_H
#define FOO_H
#include <QObject>
#include <iostream>
#include <QProcess>
class foo : public QObject
{
Q_OBJECT
public:
explicit foo(QObject *parent = nullptr);
signals:
public slots:
void process_started();
void processError(QProcess::ProcessError error);
private:
QProcess *process;
};
#endif // FOO_H
.cpp
#include "foo.h"
foo::foo(QObject *parent) : QObject(parent)
{
process = new QProcess();
bool status = QObject::connect( process, SIGNAL( started() ), this, SLOT( process_started() ) );
connect(process, &QProcess::errorOccurred, this, &foo::processError);
QString file = "/home/felippe/Área de Trabalho/Felippe/Mestrado/C_plus_plus/Codigos/build-Registration_ITK_CMAKE-Desktop_Qt_5_12_3_GCC_64bit-Default/Registration_ITK_CMAKE";
process->start(file);
std::cout << file.toStdString() << std::endl;
std::cout << "status: " << status << std::endl;
}
void foo::process_started()
{
std::cout << "It worked" << std::endl;
}
void foo::processError(QProcess::ProcessError error)
{
std::cout << "error enum val = " << error << std::endl;
}
main
#include <QCoreApplication>
#include <iostream>
#include "foo.h"
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
foo *f = new foo();
return a.exec();
}
When I run the process->start(file); I receive a error with value of 0, but when I run process->start(file, {"sudo"}); I receive a signal that the program run successfully, but anything is showed on the screen.
I'm trying to run on UBUNTU 16.04.
So, what is happening?
The most obvious difference is that system passes your string to the shell, while QProcess::start takes a command and argument list separately.
I bet you will get "file not found" if you hook to the errorOccurred signal.
Solution: remove the \\ from your string, as those are only needed if a shell is involved.

How to exchange between each other value of variables in two(or more) classes in qt 5.6?

I work on for update STM mcu from qt program. I use qt for GUI but if I have a file that has specific format, I should begin update procedure. I send start char to STM and I must send update data according to the answer. I parsed my code to classes for usefull. So UART class send data to STM and read data incoming from STM mcu. PROTOCOL class should send update data to UART accordingly to incoming data.
My problem is here. I transfered data between classes but just one direction(from PROTOCOL to UART). I sent data from PROTOCOL class to UART class. I need incoming data from STM mcu in PROTOCOL class. UART class read data but it can not send to PROTOCOL class(or PROTOCOL class can not read incoming data). How can I accomplish this?
uart.h
#ifndef UART_H
#define UART_H
#include <QObject>
#include <QtSerialPort>
#include <QtSerialPort/QSerialPort>
#include <QtSerialPort/QSerialPortInfo>
class UART : public QObject
{
Q_OBJECT
public:
explicit UART(QObject *parent = 0);
void Start();
bool Updating = true;
QByteArray received_new_data;
signals:
public slots:
void ReadFromSerialPort();
void WriteToSerialPort(const QByteArray &update_data, const qint64 &message_size);
private:
const static QString DEBUG_IDENTIFIER;
QSerialPort serial;
QByteArray data;
qint64 messageSize;
void Initialize(const QString &portName);
void Stop();
static QString PORT_NAME;
};
#endif // UART_H
uart.cpp
#include "uart.h"
#include <QDebug>
QString const UART::DEBUG_IDENTIFIER = "[UART]"; QString
UART::PORT_NAME = "/dev/ttyS1";
UART::UART( QObject *parent) : QObject(parent) {
}
void UART::Initialize(const QString &portName) {
serial.setPortName(portName);
serial.setBaudRate(QSerialPort::Baud115200);
serial.setDataBits(QSerialPort::Data8);
serial.setParity(QSerialPort::NoParity);
serial.setStopBits(QSerialPort::OneStop);
serial.setFlowControl(QSerialPort::NoFlowControl);
serial.open(QIODevice::ReadWrite);
}
void UART::ReadFromSerialPort() {
quint64 available_byte_amount = serial.bytesAvailable();
if(available_byte_amount)
{
received_new_data = serial.readAll();
qDebug() << DEBUG_IDENTIFIER << "received_data: " << received_new_data;
}
}
void UART::WriteToSerialPort(const QByteArray &update_data, const
qint64 &message_size) {
data = update_data; //! max bytes lenght
messageSize = message_size;
//! When incoming hex "10" program continue send "U" char
serial.write(data,messageSize);
serial.flush();
qDebug() <<"send";
qDebug() << "data: " << received_new_data;
}
void UART::Start() {
Initialize(PORT_NAME);
if(serial.isOpen())
{
serial.clear();
serial.clearError();
connect(&serial,SIGNAL(readyRead()), this, SLOT(ReadFromSerialPort()));
}
else
{
qDebug() << DEBUG_IDENTIFIER << "(Start)"
<< "Serial device is not open";
}
if(serial.error() == QSerialPort::NoError)
{
qDebug() << DEBUG_IDENTIFIER << "No Error";
}
else
{
qDebug() << DEBUG_IDENTIFIER << "An error occured:" << serial.errorString();
} }
void UART::Stop() {
disconnect(&serial,SIGNAL(readyRead()), this, SLOT(ReadFromSerialPort())); }
protocol.h
#ifndef PROTOCOL_H
#define PROTOCOL_H
#include <QObject>
#include <QTimer>
#include "uart.h"
class UART;
class PROTOCOL : public QObject
{
Q_OBJECT
public:
explicit PROTOCOL(UART *target_STM, QObject *parent = 0);
static UART *ptr_uart;
void gentnuma();
signals:
public slots:
void readSTM(const QByteArray &readData);
void writeSTM(const QByteArray &stm_data, const qint64 &stm_message_size);
void read_data();
private:
const static QString DEBUG_IDENTIFIER;
QTimer *m_timer;
};
#endif // PROTOCOL_H
protocol.cpp
#include <QByteArray>
#include <QDebug>
#include "protocol.h"
#include "uart.h"
QString const PROTOCOL::DEBUG_IDENTIFIER = "[PROTOCOL]";
UART *PROTOCOL::ptr_uart = NULL;
PROTOCOL::PROTOCOL(UART *target_uart, QObject *parent) : QObject(parent)
{
ptr_uart = target_uart;
QTimer *timer = new QTimer(this);
connect(timer, SIGNAL(timeout()), this, SLOT(read_data()));
timer->start(1);
}
void PROTOCOL::gentnuma()
{
UART begin;
QByteArray a = begin.received_new_data;
qDebug() << DEBUG_IDENTIFIER << "TEST:";
qDebug() << DEBUG_IDENTIFIER << "COMING DATA:"<< a; // I expected read data here
}
void PROTOCOL::readSTM(const QByteArray &readData)
{
qDebug() << DEBUG_IDENTIFIER << "read_STM_request:" << readData;
}
void PROTOCOL::writeSTM(const QByteArray &stm_data, const qint64 &stm_message_size)
{
qDebug() << DEBUG_IDENTIFIER << "send STM_data: " << stm_data;
qDebug() << DEBUG_IDENTIFIER << "send STM_data size: " << stm_message_size;
ptr_uart->WriteToSerialPort(stm_data,stm_message_size); //send data to uart
}
void PROTOCOL::read_data()
{
gentnuma();
}
Sorry bad English and long code lines. Thanks.
Solution is just a few steps away: have a signal in your UART class:
signals:
void newData();
emit it when new data are read:
void UART::ReadFromSerialPort()
{
quint64 available_byte_amount = serial.bytesAvailable();
if(available_byte_amount)
{
received_new_data = serial.readAll();
qDebug() << DEBUG_IDENTIFIER << "received_data: " << received_new_data;
emit newData();
}
}
You then connect the UART signal to the PROTOCOL slot you happen to already have, so, in PROTOCOL constructor, instead of
QTimer *timer = new QTimer(this);
connect(timer, SIGNAL(timeout()), this, SLOT(read_data()));
timer->start(1);
do:
connect(ptr_uart, SIGNAL(newData()), this, SLOT(read_data()));
This way, instead of polling for new data every second, your PROTOCOL class will be able to read new data from 'UART' whenever there's any.
But, watch out, you're doing it wrong here:
void PROTOCOL::gentnuma()
{
UART begin;
QByteArray a = begin.received_new_data;
qDebug() << DEBUG_IDENTIFIER << "TEST:";
qDebug() << DEBUG_IDENTIFIER << "COMING DATA:"<< a; // I expected read data here
}
since you're instantiating a new UART object out of the blue, and it has not (and never will have) new data to show. You already have a pointer to UART as a private class member, so you must use that one:
void PROTOCOL::gentnuma()
{
QByteArray a = ptr_uart->received_new_data;
qDebug() << DEBUG_IDENTIFIER << "TEST:";
qDebug() << DEBUG_IDENTIFIER << "COMING DATA:"<< a; // I expected read data here
}
(just as a footnote: as far as I can see, that ptr_uart doesn't really need to be static ...)

How to pass user input form the console to an object in a diffrent thread -> QTcpsocket

I am trying to create an Application that lets the user input an integer value and then sends it via tcp to my esp32.
I have set up my esp32 as a tcp server which connects to my wifi router and than shows its ipv4 adress via serial Monitor. The esp32 is connected to 2 stepperdriver and shall later control them with the data from the Application.
So my Application is working when the data that has to be sent is known before runtime for example i could create a const char* variable with the desired data and then simply send it with socket->write(foo);.
But thats not working for me because i need to get input from the console at runtime and then pass it to the function socket->write(). The problem there is that the QTcpSocket Object has to be in another thread. So i am stuck at figuring out how to pass data in between threads.
I tried to use the signal and slot mechanism to do so which if i correctly understood is meant to be used for that.
Especially this line gives me a huge headache. (the line is in the main function)
emit IO->doSendData(IO->getInput());
I try to emit the signal doSendData and pass the input from the console to the connected slot sendData() which is a method from the network class which object is in the threadNET and the object thats getting the input from the console lives in the main thread i guess thats the problem here but i have no glue how to fix it.
I dont get any error messages in QTcreator.
Thanks in advance for taking your time to help me.
If something is unclear feel free to ask me anything. Thats my first post on Stack overflow and i would appreciate any feedback on how to increase the quality of my question.
Complete code
main.cpp
//MAIN
#include <QCoreApplication>
#include <network.h>
#include <userio.h>
#include <QThread>
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
QThread* threadNET = new QThread();
network* net = new network();
userIO* IO = new userIO();
net->moveToThread(threadNET);
QObject::connect(threadNET,
&QThread::started,
net,
&network::Connect);
QObject::connect(IO,
&userIO::doSendData,
net,
&network::sendData);
threadNET->start();
while(true)
{
emit IO->doSendData(IO->getInput());
}
return a.exec();
}
network.h
//NETWORK HEADER
#ifndef NETWORK_H
#define NETWORK_H
#include <QObject>
#include <QTcpSocket>
#include <QAbstractSocket>
#include <QString>
#include <QDebug>
#include <iostream>
#include <string>
class network : public QObject
{
Q_OBJECT
public:
explicit network(QObject *parent = nullptr);
~network();
signals:
void finished(QString ffs);
void error(QString err);
public slots:
void Connect();
void sendData(QString dataToSend);
private:
QTcpSocket *socket;
};
#endif // NETWORK_H
userIO.h
//USERIO HEADER
#ifndef USERIO_H
#define USERIO_H
#include <QObject>
#include <QString>
#include <iostream>
#include <QDebug>
#include <limits>
#include <string>
class userIO : public QObject
{
Q_OBJECT
public:
explicit userIO(QObject *parent = nullptr);
QString getInput();
signals:
void doSendData(QString dataToSend);
public slots:
};
#endif // USERIO_H
network.cpp
//NETWORK SOURCE
#include "network.h"
network::network(QObject *parent) : QObject(parent)
{
}
network::~network()
{
}
void network::Connect()
{
socket = new QTcpSocket(this);
socket->connectToHost("192.168.179.167", 80);
if(socket->waitForConnected(5000))
{
std::cout << "Connected to TcpServer";
}
else
{
qDebug() << "Error: " << socket->errorString();
}
emit finished("send help");
}
void network::sendData(QString dataToSend)
{
qDebug() << "sendData" << dataToSend << "\n";
std::string convert = dataToSend.toStdString();
const char* formattedData = convert.c_str();
socket->write(formattedData);
}
userIO.cpp
//USERIO SOURCE
#include "userio.h"
userIO::userIO(QObject *parent) : QObject(parent)
{
}
QString userIO::getInput()
{
std::string rawInput;
qDebug() << "Enter the amount of steps to go\n";
std::cin >> rawInput;
while(std::cin.fail())
{
qDebug() << "Invalid input only Integer numbers are allowed\n";
qDebug() << "try again...\n";
std::cin.clear();
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
std::cin >> rawInput;
}
QString convert;
convert.fromStdString(rawInput);
return convert;
}
QString::fromStdString(const std::string &str)
is a static member that returns a copy of the str string.
calling convert.fromStdString(rawInput); does not store copied string in convert !!
you need to write :
convert = QString::fromStdString(rawInput)
OR
direct initialization:
...
QString convert(QString::fromStdString(rawInput));
return convert;

Runtime Error: could not start server

I wrote a client server program in Qt that client send some message to server but during compile the "startserver" function can't run and i get the following error:could not start server. Could you please say where is problem?
"main.cpp"
#include <QApplication>
#include "mythread.h"
#include "myserver.h"
#include "QtSql/QtSql"
#include "QMessageBox"
#include "mainwindow.h"
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
myserver server;
server.startserver();
MainWindow w;
w.show();
return a.exec();
}
"myserver.h"
#ifndef MYSERVER_H
#define MYSERVER_H
#include <QMainWindow>
#include "QTcpServer"
#include "mythread.h"
#include "QTcpSocket"
namespace Ui
{
class myserver;
}
class myserver : public QObject
{
Q_OBJECT
public:
server(QObject * parent = 0);
explicit myserver(QObject *parent = 0);
void startserver();
public slots:
void acceptConnection();
protected:
void incomingConnections(qintptr socketDescriptor);
QTcpSocket* c_client;
QTcpServer s_server;
private:
qintptr socketDescriptor;
};
#endif
"myserver.cpp"
#include "myserver.h"
#include "mythread.h"
myserver::myserver(QObject *parent) :
QObject(parent)
{
}
void myserver::startserver()
{
int port = 1234;
if(s_server.listen(QHostAddress::Any, port))
{
qDebug() << "Could not start server";
}
else
{
qDebug() << "Listening to port " ;
}
}
void myserver::incomingConnections(qintptr socketDescriptor)
{
mythread *thread = new mythread(socketDescriptor,this);
qDebug() << socketDescriptor << " Connecting...";
connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater()));
thread->start();
}
void myserver::acceptConnection()
{
c_client = s_server.nextPendingConnection();
connect(c_client,SIGNAL(readyRead()),this, SLOT(startRead()));
qDebug() << " Connecting...";
}
if(s_server.listen(QHostAddress::Any, port))
{
qDebug() << "Could not start server";
}
else
{
qDebug() << "Listening to port " ;
}
reads as "if the server CAN listen to any address on given port, print could not start server"
just change it to if (!s_server.listen(...)) and the missleading message should be gone