I'm just getting started with implementing a UDP client for my Qt application. I followed this example. I am able to send data to and receive data from a remote host. This has been verified at my remote host as well as the local client that I am developing this application for (verified locally by calling handleReadyRead() from my main.cpp). I can't seem to get the QUdpSocket to emit its readyRead signal. Why is that?
main.cpp
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QTimer>
#include "udpclient.h"
static double value = 0;
static bool flash = true;
static UDPClient client;
int update1000()
{
QByteArray Data;
Data.append((char) 0x00);
Data.append((char) 0x2c);
Data.append((char) 0x1a);
Data.append((char) 0x2c);
Data.append((char) 0x92);
Data.append((char) 0xe6);
Data.append((char) 0xf6);
Data.append((char) 0xa0);
client.SendPacket(Data);
return 0;
}
int packetReady()
{
qInfo() << "packetReady";
return 0;
}
int main(int argc, char *argv[])
{
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QGuiApplication app(argc, argv);
qmlRegisterType<HorizontalBarGraph>("com.kubie.horizontalBarGraph", 1, 0, "HorizontalBarGraph");
QQmlApplicationEngine engine;
engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
if (engine.rootObjects().isEmpty())
return -1;
QObject *object = engine.rootObjects()[0];
//qInfo() << "Initializing timer.";
QTimer timer1000;
QObject::connect(&timer1000, &QTimer::timeout, update1000);
timer1000.start(1000);
return app.exec();
}
udpclient.h
#ifndef UDPCLIENT_H
#define UDPCLIENT_H
#include <QUdpSocket>
class UDPClient : public QObject
{
Q_OBJECT
public:
explicit UDPClient(QObject *parent = nullptr);
void SendPacket(const QByteArray &buffer);
private:
QUdpSocket *socket = nullptr;
signals:
public slots:
void handleReadyRead();
};
#endif // UDPCLIENT_H
udpclient.cpp
#include "udpclient.h"
UDPClient::UDPClient(QObject *parent) :
QObject(parent)
{
socket = new QUdpSocket(this);
//We need to bind the UDP socket to an address and a port
//socket->bind(QHostAddress::LocalHost,1234); //ex. Address localhost, port 1234
socket->bind(QHostAddress::AnyIPv4,6969); //ex. Address localhost, port 1234
//connect(socket,SIGNAL(readyRead()),this,SLOT(handleReadyRead()));
connect(socket, &QUdpSocket::readyRead, this, &UDPClient::handleReadyRead);
}
void UDPClient::SendPacket(const QByteArray &buffer)
{
socket->writeDatagram(buffer, QHostAddress("192.168.174.10"), 6969);
}
void UDPClient::handleReadyRead() //Read something
{
qInfo() << socket->hasPendingDatagrams();
QByteArray Buffer;
Buffer.resize(socket->pendingDatagramSize());
QHostAddress sender;
quint16 senderPort;
socket->readDatagram(Buffer.data(),Buffer.size(),&sender,&senderPort);
qInfo() << Buffer;
//The address will be sender.toString()
}
A QML application needs (at least) a QGuiApplication to run. You will get a debug output on the command line or in your IDE debug application output window about this. To get a more fatal warning for such kind of problems you can set the environment variable QT_FATAL_WARNINGS (see QDebug documentation for more information)
Related
I am new to Qt, c++, recently I am trying to use UDP to receive data on my raspberrypi1 from another raspberrypi2 (multicast). I am able to bind both of them but I can't receive the data (nopendingdatagram). I wonder what I did wrong here. (As you might notice, the code below was taken from examples found online). Thank you in advanced for helping me.
// myudp.h
#ifndef MYUDP_H
#define MYUDP_H
#include <QObject>
#include <QUdpSocket>
class MyUDP : public QObject
{
Q_OBJECT
public:
explicit MyUDP(QObject *parent = 0);
//void HelloUDP();
signals:
public slots:
void readyRead();
private:
QUdpSocket *socket;
};
#endif // MYUDP_H
// myudp.cpp
#include "myudp.h"
MyUDP::MyUDP(QObject *parent) :
QObject(parent)
{
// create a QUDP socket
socket = new QUdpSocket(this);
bool result = socket->bind(QHostAddress("224.224.0.2"), 10002);
if(result)
{
qDebug() << "Socket Connected";
}
else
{
qDebug() << "Socket Not Connected";
}
connect(socket, SIGNAL(readyRead()), this, SLOT(readyRead()));
}
void MyUDP::readyRead()
{
// when data comes in
bool data_pending = socket->hasPendingDatagrams();
qDebug() << data_pending;
if(data_pending)
{
QByteArray buffer;
buffer.resize(socket->pendingDatagramSize());
QHostAddress sender;
quint16 senderPort;
socket->readDatagram(buffer.data(), buffer.size(),
&sender, &senderPort);
qDebug() << "Message from: " << sender.toString();
qDebug() << "Message port: " << senderPort;
qDebug() << "Message: " << buffer;
}
else
{
qDebug() << "No data";
}
}
#include <QCoreApplication>
#include "myudp.h"
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
MyUDP client;
client.readyRead();
return a.exec();
}
The result is as follows:
Socket Connected
false
No data
The problem I have in my code is, once the QML engine uplouded the QProcess stop!! Is it possible to let QProcess run while the QMLis already in operation!
the idea is: I want the user to be able to interact with only one specific mouse and one keyboard and to continually check this condition!
Can some one check what is the problem here?
int main(int argc, char *argv[])
{
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QGuiApplication app(argc, argv);
QQmlApplicationEngine engine;
bool scanForDevices=0;
USBdeviceID *usbdeviceid =new USBdeviceID();
engine.rootContext()->setContextProperty("USBdeviceID", usbdeviceid);
QProcess OProcess;
QString Command; //Contains the command to be execute
Command = "lsusb";
while (1)
{
OProcess.start(Command,QIODevice::ReadOnly); //Starts execution of command
OProcess.waitForFinished(); //Waits for execution to complete
QString StdOut = OProcess.readAllStandardOutput(); //Reads standard output
QString StdError = OProcess.readAllStandardError(); //Reads standard error
cout<<"\n Printing the standard output..........\n";
cout<<endl<<StdOut.toStdString();
bool mouse1 = StdOut.contains("ID 046d:c03e");
bool keyBoard1 = StdOut.contains("ID 413c:1003");
if (mouse1 ==1 && keyBoard1==1)
{
// start main program
// revoke A signal to tell QML the correct devices are connected
usbdeviceid->setMouse1Detected(1);
usbdeviceid->setkeyBoard1Detected(1);
engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
if (engine.rootObjects().isEmpty())
return -1;
return app.exec();
}
}
}
}
It is not necessary to create infinite loops in Qt, instead the most elegant thing is to use the signals.
#include <QGuiApplication>
#include <QProcess>
#include <QQmlApplicationEngine>
class LSUSB: public QObject
{
Q_OBJECT
public:
LSUSB(const QStringList & ids, QObject *parent=nullptr): QObject(parent), status(false), ids(ids)
{
QString command = "lsusb";
connect(&process, &QProcess::readyReadStandardOutput, this, &LSUSB::onReadyReadStandardOutput);
connect(&process, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished), this, &LSUSB::onFinished);
process.setProgram(command);
process.start();
}
Q_SIGNALS:
void isLoaded();
private Q_SLOTS:
void onReadyReadStandardOutput(){
QString stdout = process.readAllStandardOutput();
status = true;
for(const QString & id: ids){
status &= stdout.contains(id);
}
if(status){
process.kill();
Q_EMIT isLoaded();
}
}
void onFinished(){
if(!status)
process.start();
}
private:
QProcess process;
bool status;
QStringList ids;
};
int main(int argc, char *argv[])
{
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QGuiApplication app(argc, argv);
QQmlApplicationEngine engine;
LSUSB lsusb({"ID 046d:c03e", "ID 413c:1003"});
USBdeviceID usbdeviceid;
QObject::connect(&lsusb, &LSUSB::isLoaded, [&engine, &usbdeviceid](){
usbdeviceid.setMouse1Detected(1);
usbdeviceid.setkeyBoard1Detected(1);
engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
if (engine.rootObjects().isEmpty())
QCoreApplication::exit(-1);
});
return app.exec();
}
#include "main.moc"
Trying to create 2 objects (clients) living in different threads and communicating with 1 object(server) living on the main thread.
However I'm not seeing any activity on the server object.
The main goal of this code is to see how the signal slot will behave when 2 signals coming from 2 different threads are communicating with a single object on the main thread.
objects.cpp:
#include "objects.h"
Objects::Objects(QObject* parent): QObject (parent)
{
}
void Objects::printData(const QString& data)
{
qDebug() << data;
}
void Objects::process(const QString& data)
{
emit sendData(data+":processed");
}
Q_NORETURN void Objects::run()
{
while (true) {
//qDebug() << "hit" << m_rate;
emit sendData("test"+QString::number(m_rate));
QThread::sleep(m_rate);
}
}
objects.h:
#ifndef OBJECTS_H
#define OBJECTS_H
#include <QObject>
#include <QDebug>
#include <QThread>
class Objects: public QObject
{
Q_OBJECT
public:
explicit Objects(QObject* parent = Q_NULLPTR);
signals:
void sendData(const QString&);
public slots:
void printData(const QString&);
void process(const QString&);
void run();
public:
ulong m_rate;
};
#endif // OBJECTS_H
main.cpp:
#include <QCoreApplication>
#include "objects.h"
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
Objects ser;
Objects cl1;
Objects cl2;
cl1.m_rate = 1;
cl2.m_rate = 2;
QThread cl1_t;
QThread cl2_t;
QObject::connect(&cl1_t, &QThread::started, &cl1, &Objects::run);
QObject::connect(&cl2_t, &QThread::started, &cl2, &Objects::run);
QObject::connect(&cl1, &Objects::sendData, &ser, &Objects::process);
QObject::connect(&cl2, &Objects::sendData, &ser, &Objects::process);
QObject::connect(&ser, &Objects::sendData, &cl1, &Objects::printData);
QObject::connect(&ser, &Objects::sendData, &cl2, &Objects::printData);
cl1.moveToThread(&cl1_t);
cl2.moveToThread(&cl2_t);
cl1_t.start();
cl2_t.start();
return a.exec();
}
Looks like your void run() function-member blocks Qt internal event queue. Just add QCoreApplication::processEvents(); in to your void run() and it will solve your problem.
void Objects::run()
{
while (true) {
qDebug() << "hit" << m_rate;
emit sendData("test" + QString::number(m_rate));
QThread::sleep(m_rate);
QCoreApplication::processEvents();
}
}
UPD:
I will suggest you to read THIS wiki article for more detailed explanation on your problem.
I'm sending two (or more) same signals, which receives one slot, but it is only called once instead of two times.. What I'm doing wrong?
main.cpp:
#include <QCoreApplication>
#include "app.h"
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
App app;
QMetaObject::invokeMethod(&app, "run", Qt::QueuedConnection);
return a.exec();
}
app.h:
#ifndef APP_H
#define APP_H
#include <QObject>
#include "tcpserver.h"
#include "tcpsocket.h"
class App : public QObject
{
Q_OBJECT
public:
explicit App(QObject *parent = 0);
signals:
public slots:
void run()
{
qDebug() << "run()";
server.server_start(1111);
socket.connectToHost("127.0.0.1", 1111);
socket.write("hello", 5);
socket.write("olleh", 5); // should execute slot two times.
}
private:
TcpServer server;
TcpSocket socket;
};
#endif // APP_H
TcpSocket.h:
#ifndef TCPSOCKET_H
#define TCPSOCKET_H
#include <QTcpSocket>
class TcpSocket : public QTcpSocket
{
Q_OBJECT
public:
explicit TcpSocket(QObject *parent = 0);
signals:
void dataReady(QByteArray data);
public slots:
void readyRead()
{
qDebug() << "Bytes available:" << this.bytesAvailable(); // called only once.
data = this.readAll(); // just for testing.
emit dataReady(data); //
}
void disconnected();
private:
QByteArray data;
};
#endif // TCPSOCKET_H
as you can see, I'm doing two socket.write functions, which should be handled two readyRead slots, but it is called only once. I honestly don't understand what I'm doing wrong.
Regards.
I want to start a process from a QT app and catch its termination event. Its done with the method QProcess::start(). But unlike in startDetached(), the standard output of the process is redirected to a buffer. I don't want that.
I can't find how to disable it. An ugly workaround is to call setStandardOutputFile("/dev/stdout")
test.h
#ifndef MY_TEST_H
#define MY_TEST_H
#include <QCoreApplication>
class MyApp : public QCoreApplication {
Q_OBJECT
private Q_SLOTS:
void subprocessStarted();
void subprocessFinished(int);
public:
MyApp( int & argc, char ** argv );
};
#endif
test.cpp
#include "test.h"
#include <QProcess>
#include <QCoreApplication>
#include <stdio.h>
#define ENTRY printf("%s\n", __PRETTY_FUNCTION__)
MyApp::MyApp( int & argc, char ** argv ) : QCoreApplication(argc, argv) {
ENTRY;
QProcess *process = new QProcess();
//process->setStandardOutputFile("/dev/stdout");
process->start("/bin/echo aaa");
bool b;
b = connect(process, SIGNAL(started()), SLOT(subprocessStarted()));
printf("connect started %d\n", b);
b = connect(process, SIGNAL(finished(int)), SLOT(subprocessFinished(int)));
printf("connect finished %d\n", b);
}
void MyApp::subprocessStarted() {
ENTRY;
}
void MyApp::subprocessFinished(int ret) {
ENTRY;
printf("%d\n", ret);
}
int main(int argc, char *argv[]) {
ENTRY;
MyApp a(argc, argv);
return a.exec();
}
Does QProcess::closeReadChannel(ProcessChannel channel) work for you?
Closes the read channel channel. After calling this function, QProcess
will no longer receive data on the channel. Any data that has already
been received is still available for reading. Call this function to
save memory, if you are not interested in the output of the process.
Like this-
QProcess *process = new QProcess();
process->start("/bin/echo aaa");
process->closeReadChannel(QProcess::StandardOutput);
process->closeReadChannel(QProcess::StandardError);