I'm trying to write an app with Qt 6.2.4, and now I'm writing the internet-related part.Then something confused me.
I turned on Mobile Hotspot ,and my teammate and I both connected to it. After I started the server, we opened the client widget, only to find that the connection failed.Below are the code related to it.
server (Acctually it's provided by other person.To say frankly, I'm not familar with Qt's server)
NetworkServer::NetworkServer(QObject* parent)
: QTcpServer(parent)
, disconnMapper(new QSignalMapper(this))
, recvMapper(new QSignalMapper(this)) {
connect(this, &QTcpServer::newConnection, this, &NetworkServer::newconnection);
connect(this->disconnMapper, &QSignalMapper::mappedObject, this, &NetworkServer::disconnect);
connect(this->recvMapper, &QSignalMapper::mappedObject, this, &NetworkServer::receiveData);
this->listen(QHostAddress::Any, 2000);
}
client
mul_initwidget::mul_initwidget(QWidget *parent) :
QWidget(parent),
isConnected(false),
ui(new Ui::mul_initwidget),
username("user1")
{
ui->setupUi(this);
this->socket = new NetworkSocket(new QTcpSocket(), this);
qDebug()<<"mul_init create socket at" << (void*)&socket;
connect(socket, &NetworkSocket::receive, this, &mul_initwidget::receive);
//connect(socket->base(), &QAbstractSocket::disconnected, [=]() {
// QMessageBox::critical(this, tr("Connection lost"), tr("Connection to server has closed"));
//});
connect(socket->base(), SIGNAL(connected()), this, SLOT(setConnected()));
connect(socket->base(), SIGNAL(errorOccurred(QAbstractSocket::SocketError)), this, SLOT(setDisconnected(QAbstractSocket::SocketError)));
ui->label_2->hide();
socket->hello(IP,PORT);
if(isConnected)
ui->label->setText("Welcome, "+username);
else
ui->label->setText("Unconnected.");
}
Please comment if u think it's not enough to find out what's wrong, and I will add more code if I can.
Related
I am trying to develop an application that uses bluez stack along with pulseaudio and ofono in order to connect to a phone and achieve tasks such as media playback (A2DP), media control (AVRCP), and handsfree-based telephony (HFP). When I connect to my phone through bluetoothctl, it automatically connects to all the available profiles, so using all profiles A2DP, AVRCP, HFP through my program is achievable. If I don't connect to my phone using bluetoothctl, handsfree /HFP modem is not enabled/powered in ofono.
However, when I use QBluetoothSocket in Qt and connect using a profile, there is always a profile that is not connected. For example connecting to Handsfree profile, telephony works, but the media control does not work. In short, I want to be able to connect to bluetooth as bluetoothctl does. What I have in Qt is as follows (in short):
static const QList<QBluetoothUuid> audioUuids = QList<QBluetoothUuid>()
<< QBluetoothUuid::HeadsetAG
<< QBluetoothUuid::AV_RemoteControlTarget;
..
void BtConnection::setConnection(int index)
{
if(m_bluetoothSocket == nullptr) {
m_bluetoothSocket = new QBluetoothSocket(QBluetoothServiceInfo::RfcommProtocol);
qDebug() << "Created Bluetooth Socket";
}
if(m_bluetoothSocket != nullptr) {
connect(m_bluetoothSocket, SIGNAL(connected()), this, SLOT(connected()));
connect(m_bluetoothSocket, SIGNAL(disconnected()), this, SLOT(disconnected()));
connect(m_bluetoothSocket, SIGNAL(error(QBluetoothSocket::SocketError)),
this, SLOT(connectionError(QBluetoothSocket::SocketError)));
}
m_device = get(index);
// Check if an element in m_device.serviceUuids() match with an element in audioUuids
QList<QBluetoothUuid>::const_iterator uuid;
for (uuid = audioUuids.begin(); uuid != audioUuids.end(); ++uuid) {
if(m_device.serviceUuids().indexOf(*uuid) > 0) {
// This device supports one of the uuids we have scanned for
if(m_bluetoothSocket != nullptr) {
qDebug() << "*****Connecting... " << *uuid;
m_bluetoothSocket->connectToService(m_device.address(), *uuid);
return;
}
}
}
qDebug() << "*****Cannot connect to service...";
}
I would be willing to post more of the code if this is not clear to you. Any help is greately appreciated on how to connect to bluetooth with Qt as bluetoothctl does.
Not a direct answer but you might want to check KDE's KDEConnect project. It already does what you are looking for and might either be a source of inspiration or you could contribute to the project.
I am trying to clone the audio streaming model of QTCpsocket but now using QUdpsocket (virtual connection), though it looks like the code is being executed , nevertheless, effectively its not doing the job, I cant get streamed audio captured;
Main focus point is: is it possible to start a QAudioOutput with a QUDpsocket ???
Yet to clearly mention that this code works fine with a TCP socket!
Code snippet:
in server.h file
private:
QUdpSocket *socketUDP;
and in .CPP file
udpServer::udpServer(QObject *parent) : QObject(parent)
{
socketUDP = new QUdpSocket(this);
serverAddress = QHostAddress("192.168.1.8");
//socketUDP->bind(serverAddress, 1357);
socketUDP->bind(1357, QUdpSocket::ShareAddress);
socketUDP->open(QIODevice::ReadOnly);
connect(socketUDP, &QUdpSocket::readyRead, this, &udpServer::playStreamedAudio);
}
then the playstream() method:
void udpServer::playStreamedAudio() {
// set the QAudioFormat parameters of output audio device.
my_QAudioFormat = new QAudioFormat;
my_QAudioFormat->setSampleRate(48000);
my_QAudioFormat->setChannelCount(1);
my_QAudioFormat->setSampleSize(8);
my_QAudioFormat->setCodec("audio/pcm");
my_QAudioFormat->setByteOrder(QAudioFormat::LittleEndian);
my_QAudioFormat->setSampleType(QAudioFormat::UnSignedInt);
//
// get default audio output device
audiOutputDevice = QAudioDeviceInfo::defaultOutputDevice();
audiooutput = new QAudioOutput(audiOutputDevice,my_QAudioFormat, this);
// attach to socket!
qDebug() << "Playaing AudioStream";
socketUDP->open(QIODevice::ReadOnly);
audiooutput->start(socketUDP); // the Audio output device shall listen to server socket for audio
}
It turns out that UDP sockets may not suitability be interfaced as QioDevices... seems they are not intended to be, the packets are better be written to a file and then processed.
PROBLEM DEFINITION: I have an external application called runSensor that communicates with a sensor. The sensor sends its data over UDP. Using the terminal, runSensor has two arguments to communicate with the sensor for data acquisition:start and stop.
Once at the terminal I call: $ runSensor start, a sample output is as follows:
[Time 07:20:11:000]: Device PoweredOn.
[Time 07:20:11:010]: x=1.231, y=-0.022, z=0.001
[Time 07:20:11:015]: x=1.235, y=-0.024, z=0.001
[Time 07:20:11:020]: x=1.241, y=-0.024, z=0.002
[Time 07:20:11:025]: x=1.258, y=-0.027, z=0.002
I need to call start and stop using a QT-UI. For that, I have a QDialog as follows:
Dialog::Dialog(QWidget *parent) :
QDialog(parent),
ui(new Ui::Dialog)
{
ui->setupUi(this);
this->socketHandler = std::make_shared<udpHandler>();
this->runSensorStartProcess = std::make_shared<QProcess>();
this->runSensorStopProcess = std::make_shared<QProcess> ();
//--------------------------
// SIGNAL - SLOT
//--------------------------
connect(ui->startButton, SIGNAL(clicked()), this, SLOT(onStartButtonClicked()));
connect(ui->stopButton, SIGNAL(clicked()), this, SLOT(onStopButtonClicked()));
connect(this->socketHandler.get(), SIGNAL(sendUdpContent(QString)), this, SLOT(updateMessageBrowser(QString)));
connect(this->runSensorStartProcess.get(), SIGNAL(readyReadStandardError()), this, SLOT(printError()));
}
I use QProcess to call the start and stop of runSensor application. When I push the GUI's start button, data acquisition starts, but the the GUI freezes and I cann't click on the stop button.
CODE EXTRACTS: Here is how I implemented the start button click:
void Dialog::onStartButtonClicked()
{
this->runSensorStartProcess->start("start");
//this->runSensorStartProcess->waitForFinished(-1);
//--------------------------
// udp socket handler starts picking data and write it into a file
//--------------------------
if (!this->runSensorStartProcess->waitForStarted())
{
qWarning() << "Warning: Cannot start Cygwin process!";
}
}
stop button click implementation is similar:
void Dialog::onStopButtonClicked()
{
if(this->runSensorStartProcess.get() != NULL)
{
this->runSensorStartProcess->close();
}
this->runSensorStopProcess->start("stop");
if (!this->runSensorStopProcess->waitForStarted())
{
qWarning() << "Warning: Cannot stop Cygwin!";
}
}
Question:
How can I keep th GUI responsive after runSensorStartProcess starts?
How can I stop that process on demand (in fact by starting runSensorStartProcess)?
Do I need a separate thread for runSensorStartProcess?
Don't use any of the waitForXxx methods. That's all. Yes, it's that simple.
Note that for every waitForXxx method there's a signal you can attach to and thus react to the event you're looking for.
Aren't QProcess::kill and QProcess::terminate what you need?
Never. See also answer 1 and answer 2.
I'm downloading files from a remote server with Qt5.5 and everything works fine but I can't detect when a QNetworkReply returns an error.
In fact, I am trying to check the case if the user is downloading a file and suddenly, he loses his Internet connection (because why not :-) ). To do that, I start a download and unplug my Ethernet cable a few seconds after.
Is the signal QNetworkReply::error(QNetworkReply::NetworkError) emitted in this case? If yes, why am I not entering my slot in my code below?
void MyClass::download(QUrl url)
{
QNetworkRequest request = QNetworkRequest(url);
QNetworkReply *reply = pManager.get(request);
// finished() is called after error(), but try both
connect(reply, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(requestError(QNetworkReply::NetworkError)));
connect(reply, SIGNAL(finished()), this, SLOT(requestFinished()));
}
void MyClass::requestError(QNetworkReply::NetworkError err)
{
qDebug() << "error";
}
void MyClass::requestFinished()
{
qDebug() << "finished";
}
I also connected the access manager like this :
connect(&pManager, SIGNAL(finished(QNetworkReply*)), SLOT(requestFinished(QNetworkReply*)));
When the Internet connection is not interrupted, I am going in the slot requestFinished(), but if there's not Internet anymore, I am not entering any slot.
Am I doing something wrong?
Ok, nevermind, I was doing it wrong. Since I want to check the internet connection, I have to check the network availability via QNetworkAccessManager, by doing this :
QNetworkConfigurationManager manager;
pManager.setConfiguration(manager.defaultConfiguration());
connect(&pManager, SIGNAL(networkAccessibleChanged(QNetworkAccessManager::NetworkAccessibility)), this, SLOT(networkAccessibleChanged(QNetworkAccessManager::NetworkAccessibility)));
And when the Internet breaks down, I will be in the corresponding slot.
I am having problems with launching Nokia's own video player from my application that I just don't seem to be able to solve.
My first attempt included calling
Qt.openUrlExternally(url)
from QML and that seemed to do the trick just fine, except that it opened the browser every time and used it instead of the video-suite (native player).
Next I tried cuteTube -approach where I start new process like this:
QStringList args;
args << url;
QProcess *player = new QProcess();
connect(player, SIGNAL(finished(int, QProcess::ExitStatus)), player, SLOT(deleteLater()));
player->start("/usr/bin/video-suite", args);
That worked, except that it required video-suite to be closed upon calling player->start, otherwise it did nothing.
My third attempt involved starting the video-suite via QDBus, but that didn't work any better:
QList<QVariant> args;
QStringList urls;
urls << url;
args.append(urls);
QDBusMessage message = QDBusMessage::createMethodCall(
"com.nokia.VideoSuite",
"/",
"com.nokia.maemo.meegotouch.VideoSuiteInterface",
"play");
message.setArguments(args);
message.setAutoStartService(true);
QDBusConnection bus = QDBusConnection::sessionBus();
if (bus.isConnected()) {
bus.send(message);
} else {
qDebug() << "Error, QDBus is not connected";
}
The problem with this is that it requires video-suite to be up and running - autoStartService parameter didn't help either. If video-suite isn't running already, the call opens it just fine but, alas, no video starts to play.
Eventually I tried using also VideoSuiteInterface, but even having the program compile with it seemed to be difficult. When I eventually managed to compile and link all relevant libraries, the results didn't differ from option 3 above.
So, is there a way to use either VideoSuiteInterface directly or via DBus so that it would start video playback regardless of the current state of the application?
The solution was actually simpler than I really thought initially; the VideoSuiteInterface -approach worked after all. All it took was to use it properly. Here are the full sources should anyone want to try it themselves.
player.h:
#ifndef PLAYER_H
#define PLAYER_H
#include <QObject>
#include <maemo-meegotouch-interfaces/videosuiteinterface.h>
class Player : public QObject {
Q_OBJECT
private:
VideoSuiteInterface* videosuite;
public:
Player(QObject *parent = 0);
Q_INVOKABLE void play(QString url);
};
#endif // PLAYER_H
player.cpp:
#include "player.h"
#include <QObject>
#include <QStringList>
#include <QtDeclarative>
Player::Player(QObject *parent) : QObject(parent) {}
void Player::play(QString url) {
QList<QVariant> args;
QStringList urls;
urls << url;
args.append(urls);
videosuite = new VideoSuiteInterface();
videosuite->play(urls);
}
In addition you may want to connect some signals to make the UI more responsive, but basically that should do the trick.
Finally, you need to remember to add following to your .pro file and you are good to go:
CONFIG += videosuiteinterface-maemo-meegotouch