how to transfer QImage from QLocalServer to QLocalSocket - c++

I have two mac apps that communicate with each other using QLocalSocket.
Able to send the received QString but not able to send the received QImage Below is my code.
SERVER SIDE CODE
QImage image(":/asset/logo_active.png");
QByteArray ba;
qDebug() << image.sizeInBytes() <<image.size();
ba.append((char *)image.bits(),image.sizeInBytes());
qDebug() <<ba.size(); //262144
this->mSocket->write(ba);
if(!this->mSocket->waitForBytesWritten(-1))
{
qDebug() << "writen Bytes error " << this->mSocket->errorString();
}
this->mSocket->flush();
CLIENT SIDE CODE
connect(mLocalSocket,&QLocalSocket::readyRead, [&]() {
QByteArray ba;
ba = mLocalSocket->readAll();
qDebug() << "size is" << ba.size(); // size is 0
QImage image((uchar *)ba.data(),1024,768,QImage::Format_RGB32);
ui->labelStream->setPixmap(QPixmap::fromImage(img));
});
at sender 262144 is the byte-array size
but at the receiver, byte-array size is 0
Do let me know if I am missing anything.
Thanks In Advance

Finally I got the solutions I used QDataStream below is the code example.
SERVER SIDE CODE:
QDataStream T(mSocket);
T.setVersion(QDataStream::Qt_5_7);
QByteArray ba;
ba.append((char *)img.bits(),img.sizeInBytes());
T << ba;
mSocket->flush();
CLIENT SIDE CODE
QByteArray jsonData;
QDataStream socketStream(mLocalSocket);
socketStream.setVersion(QDataStream::Qt_5_7);
for (;;) {
socketStream.startTransaction();
socketStream >> jsonData;
if (socketStream.commitTransaction()) {
QImage image((uchar *)jsonData.data(),640,480,QImage::Format_RGB888);
ui->labelStream->setPixmap(QPixmap::fromImage(image));
}else {
// the read failed, the socket goes automatically back to the state it was in before the transaction started
// we just exit the loop and wait for more data to become available
break;
}
}
Thanks, Everyone for your support also Stackoverflow.

Related

QAudioOutput doesn't work correctly. I hear only noise

my program capture raw data from microphone in QT.
QAudioRecorder* recorder = new QAudioRecorder();
QAudioProbe* probe = new QAudioProbe;
connect(probe, SIGNAL(audioBufferProbed(QAudioBuffer)), this, SLOT(processBuffer(QAudioBuffer)));
QAudioEncoderSettings audioSettings;
audioSettings.setCodec("audio/mpeg");
audioSettings.setQuality(QMultimedia::HighQuality);
recorder->setEncodingSettings(audioSettings);
qDebug() << "probe ritorna " << probe->setSource(recorder); // Returns true, hopefully.
//qDebug() << "" << recorder->setOutputLocation(QUrl::fromLocalFile("test"));
recorder->record(); // Now we can do things like calculating levels or performing an FFT
myAudioServer = new MyAudioServer();
myAudioServer->startServer();
In previous code I record audio and I start a Qthread for send audio via QTcpSocket.
void QtVideoWidgetsIssueTrack::processBuffer(const QAudioBuffer& buffer){
QByteArray byteArr;
byteArr.append(buffer.constData<char>(), buffer.byteCount());
QByteArray Data = byteArr;
qDebug() << myAudioServer->isListening();
QTcpSocket* myAudioClient = myAudioServer->getSocket();
qDebug() << myAudioClient;
qDebug() << "in processBuffer";
if (myAudioClient != nullptr) {
myAudioClient->write(Data, Data.count());
myAudioClient->waitForBytesWritten();
}
}
The method processBuffer take data from microphone and send it from server to client.
void MyThreadAudioTcpSocket::readyRead()
{
while (socket->bytesAvailable() > 0) {
//fare il play da QByteArray
// get default output device
QByteArray* yourSoundData = new QByteArray(socket->readAll());
QBuffer* buffer = new QBuffer;
buffer->setData(yourSoundData->data(),yourSoundData->size());
buffer->open(QBuffer::ReadOnly);
QAudioFormat format;
format.setSampleSize(16);
format.setSampleRate(22050);
format.setChannelCount(1);
format.setCodec("audio/mpeg");
format.setByteOrder(QAudioFormat::LittleEndian);
format.setSampleType(QAudioFormat::UnSignedInt);
QAudioDeviceInfo info(QAudioDeviceInfo::defaultOutputDevice());
if (!info.isFormatSupported(format)) {
format = info.nearestFormat(format);
qDebug() << "formato non supportato";
}
QAudioOutput *output = new QAudioOutput(format);
output->moveToThread(this);
output->start(buffer);
}
}
readyRead is where data arrive from socket server. I read all data from socket, I put it in Buffer, set QAudioFormat and I create QAudioOutput linked buffer and start.
Now as you can hear from this link wav file QAudioOutput produce only noise. Why?

QSerialPort readings refresh too fast for the Qt widget

I am using QSerialPort to read from a device connected to a COM port on my computer, and it sends characters every half a second to my computer. I can read them from the qDebug window, so I know the connection works and Qt receives the data.
However I continuously read from the serial port and refresh a label widget on my GUI. The label becomes blank when I run the app, I think this problem is caused by the label name constantly refreshing.
My QserialPort is managed in the mainwindow constructor, closed in destructor, and the readings are done in a function called serialReceived(), which I believe is called (or causes the label to refresh) too often
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
serial = new QSerialPort(this);
qDebug() << "nb ports: " << QSerialPortInfo::availablePorts().length();
foreach(const QSerialPortInfo &serialPortInfo, QSerialPortInfo::availablePorts())
{
qDebug() << "name" << serialPortInfo.portName();
}
serial->setPortName("COM11");
serial->setBaudRate(QSerialPort::Baud9600);
serial->setDataBits(QSerialPort::Data8);
serial->setParity(QSerialPort::NoParity);
serial->setStopBits(QSerialPort::OneStop);
serial->setFlowControl(QSerialPort::NoFlowControl);
qDebug() << "is " << serial->open(QSerialPort::ReadOnly);
qDebug() << "err " << serial->error();
//serial->write("ok");
// Create the signal and slot
connect(serial, SIGNAL(readyRead()), this, SLOT(serialReceived()));
}
MainWindow::~MainWindow()
{
delete ui;
serial->close(); // instance is closed when mainwindow destroyed
}
void MainWindow::serialReceived()
{
QByteArray ba;
ba = serial->readAll();
ui->label->setText(serial->readAll());
qDebug()<<ba;
}
void MainWindow::serialReceived()
{
QByteArray ba;
ba = serial->readAll();
ui->label->setText(serial->readAll());
qDebug()<<ba;
}
You're first reading the data into ba, then you try to read again but since readAll() already read the data there is nothing left. You want
void MainWindow::serialReceived()
{
QByteArray ba = serial->readAll();
ui->label->setText(ba);
qDebug() << ba;
}
You just can read data at any time you want, not only by readyRead signal. The QSerialPort class will buffer all received data until you read it.
You also can append every received part of data to some scrollable QPlainTextEdit. I recommend this way.
void MainWindow::serialReceived()
{
QByteArray ba;
ba = serial->readAll();
ui->plainTextEdit->appendPlainText(ba);
}
Using timer:
connect(&m_timer, &QTimer::timeout, this, &MyClass::onTimer);
...
m_timer->start(5000);
...
void MyClass::onTimer()
{
if(serial->bytesAvailable() > 0)
{
QByteArray ba;
ba = serial->readAll();
ui->label->setText(ba);
qDebug() << ba;
}
}
You can also temporary disable visual updates of a widget using QWidget::setUpdatesEnabled(), but seems you should not miss part of the data.
Be note, QIODevice (and QSerialPort as its sublass, too) class makes no guarantee that a certain amount of data will be available on the readyRead event. For example, if you wrote 10 bytes to the port at a time on the other end, in some cases you will receive the signal that will allow less data to be available at the monent, that is, before all the transmitted bytes arrives.

toLocal8bit send over TCP

Im creating TCP Server/Client application in QT Creator framework. I want to get some data from UI input field and send it over TCP.
Im doing something like this in client application:
void MainWindow::on_btn_login_clicked()
{
QByteArray text = (ui->login_input->text()).toLocal8Bit();
char* out = text.data();
connection->ConnectAndSendData(out);
}
and in the ConnectAndSendData function:
void TcpConnect::ConnectAndSendData(const char* data)
{
socket = new QTcpSocket(this);
int port = 1234;
socket->connectToHost("localhost", port);
if(socket->waitForConnected(3000))
{
qDebug() << "connected to s. localhost at port " << port;
socket->flush();
socket->write(data, sizeof(data));
qDebug() << data << "\n";
socket->waitForReadyRead();
char* serverresponse;
socket->read(serverresponse, 128);
if(serverresponse == MESSAGE_LOGINRQ)
socket->write(data);
socket->flush();
socket->close();
}
else
{
/**/
}
}
and the data in line socket->write(data, sizeof(data)); is properly send to server, but when server echoes it, it looks like "something/x00/x00/x00/x00" or somethinglike that. Also when i to do something like this:
#define MESSAGE_WANTLOGIN "wanlogin"
socket->write(MESSAGE_WANTLOGIN, sizeof(MESSAGE_WANTLOGIN));
message is messed up with those null signs.
on the server side receiving data look as simple as:
void Thread::readyRead()
{
socket->flush();
QByteArray data = socket->readAll();
qDebug() << "data received: " << data;
if(data == MESSAGE_WANTLOGIN)
{
socket->write(MESSAGE_LOGINRQ);
} else
{
qDebug() << "error not messageloginrq";
}
}
and like u can assume, though i send "wanlogin" message, server receiving something like "wanlogin/x00/x00" and this if obviously returns false.
this trash is applied on the end of data, and this impossible to check what message was send. The other thing is that maximum size of send data is 8 chars, but also to data of this length trash is applied so it looks like "wanlogin/x00/x00"; however, when i type more chars, for example 10, the send data is just cut to 8 signs, with no /x00s.
So my question is how to clear data from those /x00s and how to send more than 1 byte of information(i need it e.g. to send login and password of user). Sorry if there's some stupid mistake, its my first client/server application which also using multithreading for each client.
sizeof(data) is 4 or 8 depending if you are on a 32-bit or 64-bit machine. It is not the size of your data, but the size (in byte) of a pointer.
So what happens is that your actual wanlogin is in fact a 6 character string, and you end up sending 2 more bytes. In this case you are lucky: the char array returned by data() is null-terminated, so you have one extra 0 that you can access, but accessing the second 0 is undefined behavior i.e anything can happen.
The solution is to use strlen() instead of sizeof. Or, better, to directly call write() with a QByteArray by changing ConnectAndSendData(const char* data) to ConnectAndSendData(const QByteArray &data).
void MainWindow::on_btn_login_clicked()
{
const QByteArray text = (ui->login_input->text()).toLocal8Bit();
connection->ConnectAndSendData(text);
}
void TcpConnect::ConnectAndSendData(const QByteArray & data)
{
socket = new QTcpSocket(this);
quint16 port = 1234;
socket->connectToHost("localhost", port);
if(socket->waitForConnected(3000))
{
qDebug() << "connected to s. localhost at port " << port;
socket->write(data);
...
}
...
}

qt c++ send 6 bytes using tcp protocol

Hi everybody, first of all I'm new on network programming so maybe this is a simple question, but I don't get it. I try to send 6 Bytes to a microcontroller using tcp socket. In order to serialize my data I'm using qdatastream and qbytearray. That's the way I try to do this:
QByteArray buffer;
QDataStream outputStream(&buffer, QIODevice::WriteOnly);
outputStream.setVersion(QDataStream::Qt_5_8);
outputStream << (quint8) 0
<< (quint8) dataMessage.prefix
<< (quint8) dataMessage.paramID
<< (quint32) dataMessage.data;
outputStream.device()->seek(0);
outputStream << (quint8)(buffer.size() - sizeof(quint8));
qDebug() << buffer;
qDebug() << quint32(dataMessage.data);
sock->write(buffer);
if(sock->write(buffer) == -1)
{
return -1;
}
sock->flush();
My struct dataMessage looks like this for example: dataMessage={15,1,9400000}
Well in my buffer I would expect this Byte sequence "\x06\xF0\x01\x00\x8F\6E\xC0"
but I always get the following Output "\x06\xF0\x01\x00\x8Fn\xC0".
What am I doing wrong?

How can i write the serial port incoming data into text file (.txt)

How I can write the serial port incoming data into text file(.txt).. The data write should have one hour interval time.
Following this the serial read data code:
void MainWindow::readData()
{
QByteArray data = serial->readAll();
QDataStream stream(data);
double value;
stream>>value;
console->putData(data);
qDebug()<<value;
}
I have tried this way but failed
void Write(QString Filename)
{
QFile mFile(Filename);
if(!mFile.open(QFile::WriteOnly | QFile::Text))
{
qDebug() << "Could not open file for writing";
return;
}
QTextStream out(&mFile);
out << data;
mFile.flush();
mFile.close();
}
I suggest you to use QByteArray for receiving and use signal readyRead() to call receive function when data is received.
QSerialPort *serialPort= new QSerialPort();
connect(serialPort, &QSerialPort::readyRead, this, &MainWindow::receiveData_WriteToFile);
This function read data and write it in file.
void MainWindow::receiveData_WriteToFile()
{
if (serialPort->isOpen())
{
QByteArray DataReceived;
QFile LogFile("D:/data.txt");
if(!LogFile.open(QFile::Append | QFile::Text))
{
//Can't Open Log File.
}
if(serialPort->bytesAvailable())
{
DataReceived = serialPort->readAll();//All Data Received Successfully.
if(DataReceived.size() > 0)
{
if(LogFile.isOpen())
{
QTextStream in(&LogFile);
in << DataReceived;
}
LogFile.close();
}
else
{
//Fail To Receive Data.
}
}
LogFile.close();
}
}
readyRead() : This signal is emitted once every time new data is available for reading from the device's current read channel. It will only be emitted again once new data is available, such as when a new payload of network data has arrived on your network socket, or when a new block of data has been appended to your device.
output file:
This is a sample project for your question on github download here.