QNetworkAccessManager send data incomplete - qt

I have a trouble with QNetworkAccessManager in windows. I wrote the following code to submit request ,it works on ubuntu perfectly but on windows send just 16384 bytes!! It seems request execute just once and freeze.
QString concatenated = username + ":" + pass;
QByteArray hash = concatenated.toLocal8Bit().toBase64();
QString headerData = "Basic " + hash;
QNetworkRequest request = QNetworkRequest(QUrl(baseURL));
request.setRawHeader("Authorization", headerData.toLocal8Bit());
request.setRawHeader("Content-Type", "application/json");
QNetworkReply * reply = nam->post(request,data);
connect(reply,&QNetworkReply::uploadProgress,this,&myClass::uploadProgress);
in uploadProgress method:
qDebug() << sent << " " << total;
if(total && sent){
int result = (sent*100)/total;
emit uploaded(result);
}
output:
16384 632054 // AND EVERY THINGS STOP UNTIL I GET QNetworkReply::RemoteHostClosedError ERROR CODE

After two days finally, I found why it happened! It because I emit the signal in uploadProgress directly! I changed the uploadProgress code like below and it works perfectly now!
qDebug() << sent << " " << total;
if(total && sent){
int result = (sent*100)/total;
QTimer::singleShot(5,[this,result](){
emit uploaded(result);
}
}

Related

Error transferring https://speech.googleapis.com/v1/speech:recognize?key=,myKey> - server replied: Bad Request [Problem on Windows OS]

I am using google speech-to-text api to convert my audio file to text. Following is my code(in Qt):
`QString fileName = QDir::currentPath() + "/audio.wav"; //this is my audio file
QFile audioFile(fileName);
if(!audioFile.open(QIODevice::ReadOnly | QIODevice::Text)){
QMessageBox::critical(0,"Error",fileName+" Not found!");
ui->pushButton_4->setText("Speech to text");
return;
}
int idx = ui->comboBox->currentIndex();
QString enc;
if (idx == -1)
enc = "en-US";
else
enc = ui->comboBox->itemData(idx).toString(); //Language selected by user
QByteArray audioData=audioFile.readAll();
QUrl url("https://speech.googleapis.com/v1/speech:recognize");
QUrlQuery query;
query.addQueryItem("key","myKeyHere...");
url.setQuery(query);
QNetworkRequest request(url);
request.setHeader(QNetworkRequest::ContentTypeHeader,"audio/x-flac");
QJsonObject json;
QJsonObject config;
config["encoding"]="FLAC";
config["sampleRateHertz"]=44100;
config["languageCode"]=enc;
json["config"]=config;
QJsonObject audio;
audio["content"]=QString::fromLatin1(audioData.toBase64());
json["audio"]=audio;
QByteArray jsonData=QJsonDocument(json).toJson();
QNetworkAccessManager *manager=new QNetworkAccessManager();
QNetworkReply *reply=manager->post(request,jsonData);
QObject::connect(reply,&QNetworkReply::finished,[this,reply](){
if(reply->error()!=QNetworkReply::NoError){
QMessageBox::critical(0,"Error Occured",reply->errorString());
qDebug() << reply->readAll();
ui->pushButton_4->setText("Speech to text");
return;
}
else if(reply->error()==QNetworkReply::UnknownNetworkError){
QMessageBox::warning(0,"Network Error","Please check your internet connection and try again!");
ui->pushButton_4->setText("Speech to text");
}
else if(reply->isFinished() && reply->error()==QNetworkReply::NoError){
QJsonDocument responseJson=QJsonDocument::fromJson(reply->readAll());
QJsonObject object=responseJson.object();
QString ResponseText=object["results"].toArray()[0].toObject()
["alternatives"].toArray()[0].toObject()["transcript"].toString();
QTextCursor cur = curr_browser->textCursor();
qDebug() << "Response Data :" << ResponseText;
cur.insertText(ResponseText);
ui->pushButton_4->setText("Speech to text");
}
reply->deleteLater();
});`
This code is working perfectly on Ubuntu but not on windows. When i run this on Ubunutu, i am receiving the response, but on windows i receive the following error:
Error transferring https://speech.googleapis.com/v1/speech:recognize?key=,myKey> - server replied: Bad Request
Following is the code to record an audio file:
`if (m_audioRecorder->state() == QMediaRecorder::StoppedState) {
QString fileName = QDir::currentPath() + "/audio.wav";
m_audioRecorder->setOutputLocation(QUrl::fromLocalFile(fileName));
qDebug()<<"Recording your audio!!";
ui->pushButton_4->setText("Stop ?");
QAudioEncoderSettings settings;
settings.setCodec("audio/x-flac");
settings.setSampleRate(0);
settings.setBitRate(0);
settings.setChannelCount(1);
settings.setQuality(QMultimedia::EncodingQuality(2));
settings.setEncodingMode(QMultimedia::ConstantQualityEncoding);
m_audioRecorder->setEncodingSettings(settings, QVideoEncoderSettings(), "");
m_audioRecorder->record();
}
else {
qDebug()<<"stopped your recording!";
ui->pushButton_4->setText("Processing ...");
m_audioRecorder->stop();
speechToTextCall(); //calling the code to send request to google api
}`
Can anyone help please?
I tried changing the encodig and container type, but nothing worked on Windows.
I have found the solution of above problem. Windows does not recognize the auido/x-flac encoding so i modified my encoding code as follows:
'
#ifdef Q_OS_WIN
settings.setCodec("audio/pcm");
#else
settings.setCodec("audio/x-flac");
#endif
'
I made the same changes at other two places where encoding was set and it worked on windows as well.

Qmqtt QObject::connect: Cannot queue arguments of type 'ClientState' (Make sure 'ClientState' is registered using qRegisterMetaType().)

I am creating a thread and inside that thread :
m_client = new QMqttClient(this);
m_client->setHostname("ps01.xx.com");
m_client->setPort(1883);
m_client->setClientId("Sas-RASPi-001");
m_client->connectToHost();
connecting to the mqt broker.
any signal connecting attempt like :
QObject::connect(m_client, &QMqttClient::stateChanged, this, &Messenqt::updateLogStateChange);
produce an error like :
QObject::connect: Cannot queue arguments of type 'ClientState'
(Make sure 'ClientState' is registered using qRegisterMetaType().)
I added :
qRegisterMetaType<QMqttClient::ClientState>("QMqttClient::ClientState");
in the beginning of the code (above code)
still same problem.
What is the proper way to use mqt from different thread in QT signal/slot way ?
EDIT:
for (int i = 20 ; i < 20 ; i++){
QThread::sleep(1);
if(m_client->publish(topic_, QString("testing. . . ").toLocal8Bit() , 1 ,true) == -1;
qDebug() << " error" <<;
}
Hi,
I am using qmqtt in a for loop with sleep 1 second and then process waiting to send messages until all 20 messages published.
When the loop finishe all 20 messages send .
But . if we will not use QThread::sleep(1) . then each messages sending individually. why . ?
Is there any way to force send to each messages immediatelly when its published?
EDIT 2
Below example not sending the images to the broker. It is blocking some place somewhere. I need flush the messages :)
minimal example :
m_client = new QMqttClient(this);
m_client->setHostname("ps01.xxx.com");
m_client->setPort(1883);
m_client->setClientId("RASPBERRY-009");
m_client->setUsername("vv");
m_client->setPassword("vv");
m_client->setCleanSession(false);
m_client->connectToHost();
//yeni slot mekanizmasi. kendi icinde &Publisher örneği..
QObject::connect(m_client, &QMqttClient::stateChanged, this, &Publisher::updateStateChange);
QObject::connect(m_client, &QMqttClient::connected, this, &Publisher::sendMessages);
an the send message:
void Publisher::sendMessages()
{
QDir dir("/ram");
int count = 0;
QThread::sleep(5);
while (true){
QStringList images_metas = dir.entryList(QStringList() << "*.png" ,QDir::Files);
if (images_metas.size() > 0){
foreach(QString filename, images_metas) {
dataLoad *dl = new dataLoad;
QString img_path = "/ram/" + filename;
QImage img(img_path);
qDebug() << " : : : " << QImage("/ram/00-02-2018-04-05-2.png").size() << endl;
dl->image = img;
dl->text = "Deneme MEsajıdır . . ";
QByteArray byteArray_;
QDataStream stream(&byteArray_, QIODevice::WriteOnly);
stream.setVersion(QDataStream::Qt_5_10);
stream << dl->image << dl->text;
qDebug() << count++ << " sending : " << byteArray_.size() << " " << filename << endl;
qDebug() << testPublish(byteArray_)<< endl;
}
}
else {
qDebug() << " folder is empty waiting... " << endl;
}
//Check every 1 second
QThread::sleep(1);
}
}
and the publishing:
qint32 Publisher::testPublish(QByteArray &bytarray)
{
QMqttTopicName topic_ = QString("qtmqtt/topic1");
QString mesaj = ".x.x.x.x.x.x.x.";
auto id = m_client->publish(topic_, mesaj.toLocal8Bit() , 1 ,true);
return id;
}
Please try below code:
msg_timer = new QTimer(this);
//TODO big chip save timer.
connect(msg_timer, SIGNAL(timeout()) , this , SLOT(sendMessages()));
msg_timer->start(1000);
dont use while loop. It is blocking everything..
Best
I get a solution to the problem of "Qmqtt QObject::connect: Cannot queue arguments of type 'ClientState' (Make sure 'ClientState' is registered using qRegisterMetaType().)" caused by working in threads. Although I have not made clear the specific meaning, at least it can work well.
You can try it:
connect(m_client, &QMqttClient::stateChanged, [&](QMqttClient::ClientState state){
qDebug()<< state;
});

Strange reply when uploading zip file to amazon S3 using REST ,QT and PUT request

iam trying to upload zip file to S3 amazon but i have problem.
i am using QT : sending request and receiving reply.
i am sending the URL with zip file here is the code :
QFile *file = new QFile(fileName);
QString fileSize = QString::number(file->size());
file->open(QIODevice::ReadOnly);
QByteArray data(file->readAll());
QNetworkRequest req;
QNetworkReply* rep;
req.setUrl(QUrl(url /*cant post the real URL*/));
req.setRawHeader(QString("Content-Length").toUtf8(), fileSize.toUtf8());
rep = m_manager->post(req, data);
connect(rep, SIGNAL(finished()), &loop, SLOT(quit()));
loop.exec();
CheckReply(rep);
and here is CheckReply function
bool CheckReply(QNetworkReply *reply)
{
if (reply->error())
{
qDebug() << "ERROR!";
qDebug() << reply->errorString();
return false;
}
else
{
qDebug() << reply->header(QNetworkRequest::ContentTypeHeader).toString();
qDebug() << reply->header(QNetworkRequest::LastModifiedHeader).toDateTime().toString();
qDebug() << reply->header(QNetworkRequest::ContentLengthHeader).toULongLong();
qDebug() << reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
qDebug() << reply->attribute(QNetworkRequest::HttpReasonPhraseAttribute).toString();
return true;
}
}
the problem is , CheckReply() shows this msg : "Error downloading -request URL-".
why this happens , it is upload NOT download.
thanks
OK i find the problem , in case any one face the same problem.
the bug was that i use QUrl(QSting) , to set the request url.
instead of that use this : QUrl::fromEncoded(QByteArray) or
QUrl::fromEncoded(/your QString/.toUtf8()).

Read all input from QSerialPort

I am receiving data in this shape:
Q1\n
9.70E-6\n
OK>
from an external device via QSerialPort, but with my reading routine
QString request = "Hello";
qDebug() << "TransAction started!";
QByteArray requestData = request.toLocal8Bit();
qDebug() << "Writing data: " << requestData;
serial->write(requestData);
qDebug() << "Data written";
if(serial->waitForBytesWritten(waitTimeout))
{
if(serial->waitForReadyRead(waitTimeout))
{
qDebug() << "Waiting for data!";
QByteArray responseData = serial->readAll();
while(serial->waitForReadyRead(100))
responseData += serial->readAll();
responseData.replace('\n', ' ');
QString response(responseData);
QByteArray response_arr = response.toLocal8Bit();
qDebug() << "Response is: " << response_arr.toHex();
emit this->response(response);
}
else
{
qDebug() << "Wait read response timeout";
emit this->timeout(tr("Wait read response timeout %1").arg(QTime::currentTime().toString()));
}
}
else
{
qDebug() << "Wait write request timeout!";
emit this->timeout(tr("Wait write request timeout %1").arg(QTime::currentTime().toString()));
}
I only get
Q1
as response. How can I modify my code such that I am able to read all input data?
Update:
When testing it with the serial port script described here: https://stackoverflow.com/a/7654527/2546099, everything works. Apparently the problem is that the qt-version stops reading after the first line break. This problem consists also if I add
char buffer[1000];
for(int i = 0; i < 1000; i++)
{
int tmp = serial->read(buffer, 1000);
if(tmp > 0)
qDebug() << buffer;
}
directly after the line
qDebug() << "Waiting for data!";
Then I still only get the first line (without the \n). Changing times does not change the received data.
The answer to my problem is (partly) described in this question: External vs internal declaration of QByteArray. My problem (why I did not receive any further data) was that I did not send a \x00D after the input line, thus the device just echoed my input, and was waiting for the Enter afterwards. After the input looks exactly as the first line, I misunderstood it for just getting the first line, and nothing else.

Reusing ASIO connection, read_some exception

I am currently trying to figure out how to properly reuse an asio socket. I am able to successfully send out a request, and get the result. The second time I send out a request, I get an exception: read_some: End of file. The second write seems to work fine, I see the second http request going out over wireshark. I am thinking that there is left over information on the socket that is corrupting my connection in some way. Any help would be appreciated with this issue. Here is the code I am using:
persistent_connection::persistent_connection(std::string ip, std::string port):
io_service_(), socket_(io_service_), is_setup_(false)
{
boost::asio::ip::tcp::resolver resolver(io_service_);
boost::asio::ip::tcp::resolver::query query(ip,port);
boost::asio::ip::tcp::resolver::iterator iterator = resolver.resolve(query);
boost::asio::ip::tcp::endpoint endpoint = *iterator;
socket_.async_connect(endpoint, boost::bind(&persistent_connection::handler_connect, this, boost::asio::placeholders::error, iterator));
io_service_.run();
}
void persistent_connection::handler_connect(const boost::system::error_code &ec, boost::asio::ip::tcp::resolver::iterator endpoint_iterator)
{
if(ec)
{
std::cout << "Couldn't connect" << ec << std::endl;
return;
}
else
{
boost::asio::socket_base::keep_alive keep_option(true);
socket_.set_option(keep_option);
}
}
void persistent_connection::write(std::string message)
{
std::string request_stream = "GET /" + message + " HTTP/1.0\r\n";
request_stream += "HOST: 10.1.10.220";
request_stream += "Accept: */*\r\n";
request_stream += "Connection: keep-alive\r\n\r\n";
try
{
boost::asio::write(socket_, boost::asio::buffer(request_stream, request_stream.size()));
}catch(std::exception& e)
{
std::cout << "Write exception: " << e.what() << std::endl;
}
boost::array<char,8192> buf;
try
{
socket_.read_some(boost::asio::buffer(buf));
}catch(std::exception& e)
{
std::cout << "Read exception: " << e.what() << std::endl;
}
std::string response = buf.data();
std::cout << response << std::endl;
}
Edit: Added main function.
int main()
{
persistent_connection p("10.1.10.220", "80");
std::string check;
do
{
std::cin >> check;
if(check.compare("s") == 0)
{
std::cout << "Sending" << std::endl;
p.write("100");
}
}while(check.compare("x") != 0);
}
The fact you get this exception when trying to read_some means that the HTTP server closes the connection after the first request is over, i.e. the server ignores "Connection: keep-alive" header (note that HTTP 1.0 servers don't necessarily support persistent connections).
However, in 1.1 version connections are persistent by default, so requesting "HTTP/1.1" should solve this issue.

Resources