I'm new with Qt Creator and I'm trying to read data from a light sensor communicating by I2C. I made a class PortListener that should return data received on the console once called.
PortListener::PortListener(const QString &portName)
{
this->port = new QSerialPort();
port->setPortName(portName);
port->setBaudRate(QSerialPort::Baud9600);
port->setDataBits(QSerialPort::Data8);
port->setParity(QSerialPort::NoParity);
port->setStopBits(QSerialPort::OneStop);
port->setFlowControl(QSerialPort::NoFlowControl);
port->open(QIODevice::ReadWrite);
QByteArray readData = port->readAll();
qDebug() << "message:" << readData;
}
But the only message I have is:
QIODevice::read (QSerialPort): device not open
message: ""
I don't understand what that mean?
1.Open the serialport,then set the parameters.
PortListener::PortListener(const QString &portName)
{
this->port = new QSerialPort();
port->open(QIODevice::ReadWrite);
port->setPortName(portName);
port->setBaudRate(QSerialPort::Baud9600);
port->setDataBits(QSerialPort::Data8);
port->setParity(QSerialPort::NoParity);
port->setStopBits(QSerialPort::OneStop);
port->setFlowControl(QSerialPort::NoFlowControl);
}
2.Connect the readyRead signal to a slot, and the slot is like this.
void PortListener::readyReadSlot()
{
while (!port.atEnd()) {
QByteArray data = port.readAll();
}
}
This is much more like the QextSerialPort, the following is the code from my application.
void SpClient::start()
{
myComClient = new QextSerialPort(Setting::devCom);
if(myComClient->open(QIODevice::ReadWrite))
{
qDebug() << "open " << Setting::devCom << "as client success";
}
myComClient->setBaudRate(BAUD9600);
myComClient->setDataBits(DATA_8);
myComClient->setParity(PAR_NONE);
myComClient->setStopBits(STOP_1);
myComClient->setFlowControl(FLOW_OFF);
myComClient->setTimeout(50);
....
}
My guess is your code is failing to open the serial port, I have run into permissions issues under linux opening USB ports. You will just need to do a chmod to grant your $USER access mostly.
Related
I'm trying to send some data from QLocalSocket to QLocalSever in a loop. Sever only gets the first data and not receiving subsequent data, but if I introduce 1 mec delay between each call from the client then the server starts to receive everything. Please check out the below Client & Server code.
client.cpp
#include "client.h"
#include "QDataStream"
#include <QTest>
TestClient::TestClient() : m_socket{new QLocalSocket(this)}{
m_socket->connectToServer("TestServer");
if (m_socket->waitForConnected(1000)) {
qDebug("socket Connected!");
}
connect(m_socket, &QLocalSocket::readyRead, this, &TestClient::onNewData);
}
void TestClient::onNewData() {
qCritical() << "data received from server";
}
void TestClient::sendDataToServer() {
QByteArray block;
QDataStream out(&block, QIODevice::WriteOnly);
out.setVersion(QDataStream::Qt_5_10);
QString testString = "test data";
out << quint32(testString.size());
out << testString;
m_socket->write(block);
m_socket->flush();
}
void TestClient::startClient() {
for(int i = 0; i < 5; i++) {
//QTest::qWait(1); //works if I uncomment this line
sendDataToServer();
}
}
server.cpp
#include "server.h"
TestServer::TestServer() : m_server{new QLocalServer(this)} {
QLocalServer::removeServer("TestServer");
if (!m_server->listen("TestServer")) {
qCritical() << "couldn't connect to server";
}
connect(m_server, &QLocalServer::newConnection, this, &TestServer::onNewConnection);
}
void TestServer::onNewConnection() {
m_socket = m_server->nextPendingConnection();
connect(m_socket, &QLocalSocket::readyRead, this,
&TestServer::onNewData);
connect(m_socket, &QLocalSocket::disconnected, m_socket,
&QLocalSocket::deleteLater);
}
void TestServer::onNewData() {
QLocalSocket* client = qobject_cast<QLocalSocket*>(sender());
client->readAll();
qCritical() << "data read by server";
}
from the qt doc, it's stated that
readyRead() is not emitted recursively; if you reenter the event loop
or call waitForReadyRead() inside a slot connected to the readyRead()
signal, the signal will not be reemitted (although waitForReadyRead()
may still return true).
so is this my problem? adding timer is the only solution here?
You can compile this test project -> http://www.filedropper.com/testsocket
There are various methods of reading and writing from a QTcpSocket using a QDatastream as seen here
The difference is, I will be sending more than "one packet" or blocks.
A basic implementation on the server (sending) side and client (recieving) is seen below - only the actual sending and receiving snippets are shown
More Info, What I tried:
When writing to a QTcpSocket, I attempted to use the QTcpSocket::canReadLine() however this fails straightup after the QTcpSocket::waitForReadReady() signal fires.
I then tried QDataStream::atEnd() in a while loop which causes a system crash :(
The code below shows my latest attempt of going through the QDataStream docs, and utilzing the commitTransaction where it states
If no full packet is received, this code restores the stream to the initial position, after which you need to wait for more data to arrive.
Under the heading Using Read Transactions. But ofcourse, this just reads one block that is sent, i.e the first block.
Question:
When writing to a QTcpSocket multiple times, and flushing the socket each time to send that data, how can I read this from a QTcpSocket as it is send, keep the original "send structure"?
The example below only reads the first block and ends. I would like to read the block containing "Response 2" and "Response 3".
Code Implementations:
//server.h
//...
QTcpSocket *clientSocket = nullptr;
QDataStream in;
//...
//server.cpp
//...
in.setDevice(clientSocket);
in.setVersion(QDataStream::Qt_4_0);
in.startTransaction();
QString nextFortune;
in >> nextFortune;
if (in.commitTransaction())
ui->lblOut->setText(nextFortune);
if (clientSocket != nullptr) {
if (!clientSocket->isValid()) {
qDebug() << "tcp socket invalid";
return;
}
if (!clientSocket->isOpen()) {
qDebug() << "tcp socket not open";
return;
}
QByteArray block;
QDataStream out(&block, QIODevice::WriteOnly);
out.setVersion(QDataStream::Qt_4_0);
out << QString(QString("Response:") + nextFortune);
if (!clientSocket->write(block)){
QMessageBox::information(this, tr("Server"),tr("Could not send message"));
}
clientSocket->flush();
// block.clear();
out << QString("Response number 2");
if (!clientSocket->write(block)){
QMessageBox::information(this, tr("Server"),tr("Could not send message"));
}
clientSocket->flush();
// block.clear();
out << QString("Response number 3 here, and this is the end!");
if (!clientSocket->write(block)){
QMessageBox::information(this, tr("Server"),tr("Could not send message"));
}
clientSocket->flush();
clientSocket->disconnectFromHost();
}
//...
And the client side
//client.h
//...
QTcpSocket *tcp_con = nullptr;
QDataStream in;
//...
//client.cpp
//...
if(!tcp_con->waitForReadyRead()){
qDebug(log_lib_netman_err) << "tcp con timeout for reading";
tcp_con->disconnectFromHost();
return ReturnObject(ReturnCode::SocketError, QString());
}
in.setDevice(tcp_con);
in.setVersion(QDataStream::Qt_4_0);
in.startTransaction();
QList<QString> data_rcv = QList<QString>();
QString s;
// while (tcp_con->canReadLine()) {
// in >> s;
// data_rcv.push_back(s);
// }
// while (!in.read) {
in >> s;
data_rcv.push_back(s);
// }
while (!in.commitTransaction()){
qDebug(log_lib_netman_info) << "waiting for more data";
in >> s;
data_rcv.push_back(s);
// qDebug(log_lib_netman_err) << "Unable to send data to server";
// tcp_con->disconnectFromHost();
// return ReturnObject(ReturnCode::FailedReceiving, QString());
}
// if (s.isEmpty()) {
// qDebug(log_lib_netman_err) << "Empty response recieved";
// tcp_con->disconnectFromHost();
// return ReturnObject(ReturnCode::NoDataRecieved, QString());
// }
tcp_con->disconnectFromHost();
return ReturnObject(ReturnCode::ReceivedSuccess, data_rcv);
Help would be greatly appreciated!
I have implemented a ssl server using QSslSocket and run it correctly. But I have some problem with it that I couldn't solve them immediately.
I thought that just connecting readyRead() signal to a slot for reading buffer is sufficient to do that but I have recognized that the readyRead() does not emit at all in this situation and I must also use waitForReadyRead() function in my code. But the problem is using this function cause blocking read the buffer. Actually I want to know how I can read buffer when data has arrived without blocking?
Bellow is my implemented ssl server:
#include "sslserver.h"
#include <QtNetwork/QTcpServer>
#include <QtNetwork/QTcpSocket>
#include <QFile>
#include <QtNetwork/QSslKey>
#include <QtNetwork/QSslConfiguration>
#include <QtNetwork/QSslError>
SslServer::SslServer(QObject *parent) : QTcpServer(parent)
{
server = new QTcpServer(this);
if(!server->listen(QHostAddress::Any, 9996))
{
qDebug() << "Server could not start";
}
else
{
qDebug() << "Server started!";
}
connect(server, SIGNAL(newConnection()), this, SLOT(newConnectionRecognized()));
}
void SslServer::showErrors()
{
this-> err = socket->sslErrors();
for(int i=0;i<err.size();i++)
qDebug() << err[i];
}
SslServer::~SslServer()
{
}
void SslServer::newConnectionRecognized()
{
incomingConnection(server->nextPendingConnection()->socketDescriptor());
}
void SslServer::incomingConnection(qintptr socketDescriptor)
{
socket = new QSslSocket(this);
socket->setProtocol(QSsl::SslV3);
connect(socket, SIGNAL(sslErrors(QList<QSslError>)), this, SLOT(showErrors()));
connect(socket, SIGNAL(encrypted()), this, SLOT(ready()));
connect(socket, SIGNAL(readyRead()), this, SLOT(readChannel()));
// Read Key from file
QByteArray key;
QFile KeyFile("server.key");
if(KeyFile.open(QIODevice::ReadOnly))
{
key = KeyFile.readAll();
KeyFile.close();
}
else
{
qDebug() << KeyFile.errorString();
}
QSslKey sslKey(key, QSsl::Rsa);
socket->setPrivateKey(sslKey);
// Load server ssl certificate from file
QByteArray cert;
QFile CertFile("server.csr");
if(CertFile.open(QIODevice::ReadOnly))
{
cert = CertFile.readAll();
CertFile.close();
}
else
{
qDebug() << CertFile.errorString();
}
QSslCertificate sslCert(cert);
socket->setLocalCertificate(sslCert);
QSslConfiguration cfg = socket->sslConfiguration();
cfg.caCertificates();
if (!socket->setSocketDescriptor(socketDescriptor))ee
{
qDebug() << ("! Couldn't set socket descriptor");
delete socket;
return;
}
socket->startServerEncryption();
if (socket->isEncrypted())
emit socket->encrypted();
if(!socket->waitForEncrypted(3000)) {
qDebug("Wait for encrypted!!!!");
return;
}
while (true) {
socket->waitForReadyRead();
}
}
void SslServer::readChannel()
{
QByteArray qstrbytes = socket->readLine();
qDebug() << qstrbytes;
}
void SslServer::ready()
{
qDebug() << "Encrypted";
}
I have found the problem when I implement another client/server but this time with QTcpSocket. I dont know exactly why but I guess the problem is because of using socketDescriptor for creating a QSslSocket. When I created client and server with QTcpSocket they works perfectly without any event loop and only by connecting readyRead() signal to an slot. After that in order to testing some situation I have create QTcpSocket using socketDescriptor. Then I found the problem is from creating socket using socketDescriptor because this time the readyRead() signal doesn't work as before.
I'm trying to redirect the output of QProcess live into my console.
Here is the code I'm using:
QProcess *process = new QProcess(this);
connect (process, SIGNAL(readyReadStandardOutput()), this, SLOT(processOutput()));
connect (process, SIGNAL(readyReadStandardError()), this, SLOT(processOutput()));
process->start(program);
void MainWindow::processOutput()
{
qDebug() << process->readAllStandardOutput();
}
However the above does not redirect the output stream live into my console. The processOutput() function seems to be called every time the program tries to print something but all the output seems to be buffered by QProcess and printed on my console only after the completion of the program started by QProcess. Any help would be greatly appreciated. Thanks!!
I have a MessageHandler Class which redirects all qDebug messages to an Console TabOutput in my GUI App.
MessageHandler::handleMessages(QtMsgType type, const QMessageLogContext &cntxt, const QString &msg)
{
switch(type)
{
case QtDebugMsg:
if(!m_appOutput)
{
fprintf(stderr, "Debug :: %s\n", qPrintable(msg));
}
else
{
m_appOutput->append(msg);
}
break;
}
}
In my main.cpp, I have registered my message handler class as follows:
qInstallMessageHandler(MessageHandler::handleMessages);
The m_appOutput is a QTextEdit which is present in the MainWindow where all my app output messages are printed.
I have two QT apps. One app can be considered to hold a big data and it sends about 10 KB of data chunk every second to second application.
Earlier I tried using QUdpSocket to transmit the data but due to MTU limitation of about 2-5K and need to divide and reunite the data myself, I switched to QTcpSocket.
Sometimes data is sent correctly with QTcpSocket (especially if I write data very frequently ~every 100 ms) but sometimes data is not sent at all. Not even after 5 sec. And sometimes several data chunks are internally buffered for a long period (several seconds) and then sent together.
m_socket = new QTcpSocket(this);
m_socket->connectToHost(QHostAddress::LocalHost, 45454);
sendDataEverySec()
{
QByteArray datagram(10000, 'a');
qint64 len = m_socket->write(datagram);
if(len != datagram.size())
qDebug() << "Error"; //this NEVER occurs in MY case.
m_socket->flush();
}
On receiver side, I use readyRead signal to know when data has arrived.
How can I ensure that data is sent immediately? Are there any better alternatives for what I am trying to do?
Edit:: When I am writing after long gaps of 1 second, I receive "QAbstractSocket::SocketTimeoutError" on receiver side everytime sender sends data. This error is not received if sender writes data frequently.
Is it OKAY to use QTcpSocket to stream data the way I am doing????
Edit 2: On receiver side, when readyRead signal is emitted, I was again checking while(m_socket->waitForReadyRead(500)) and I was getting "QAbstractSocket::SocketTimeoutError" due to this. Also, this check was preventing delivering of single chunks.
After going through docs more, it seems readyRead will be continuously emitted when new data is available, so no need for waitForReadyRead.
I am receiving all data sent but still data does not come immediately. Sometimes two-three chunks are merged. This may be because of delay on receiver side in reading data etc.
On receiver side, when readyRead signal is emitted, I was again checking while(m_socket->waitForReadyRead(500)) and I was getting "QAbstractSocket::SocketTimeoutError" due to this. Also, this check was preventing delivering of single chunks.
After going through docs more, it seems readyRead will be continuously emitted when new data is available, so there is no need for waitForReadyRead.
It had solved my issue.
my tipical solution for client server app.
on server side :
class Server: public QTcpServer {
public:
Server(QObject *parent = 0);
~Server();
private slots:
void readyRead();
void disconnected();
protected:
void incomingConnection(int);
};
on cpp:
void Server::incomingConnection(int socketfd) {
QTcpSocket *client = new QTcpSocket(this);
client->setSocketDescriptor(socketfd);
connect(client, SIGNAL(readyRead()), this, SLOT(readyRead()));
connect(client, SIGNAL(disconnected()), this, SLOT(disconnected()));
}
void Server::disconnected() {
QTcpSocket *client = (QTcpSocket*) sender();
qDebug() << " INFO : " << QDateTime::currentDateTime()
<< " : CLIENT DISCONNECTED " << client->peerAddress().toString();
}
void Server::readyRead() {
QTcpSocket *client = (QTcpSocket*) sender();
while (client->canReadLine()) {
//here i needed a string..
QString line = QString::fromUtf8(client->readLine()).trimmed();
}
}
on client:
class Client: public QTcpSocket {
public:
Client(const QHostAddress&, int, QObject* = 0);
~Client();
void Client::sendMessage(const QString& );
private slots:
void readyRead();
void connected();
public slots:
void doConnect();
};
on cpp:
void Client::readyRead() {
// if you need to read the answer of server..
while (this->canReadLine()) {
}
}
void Client::doConnect() {
this->connectToHost(ip_, port_);
qDebug() << " INFO : " << QDateTime::currentDateTime()
<< " : CONNESSIONE...";
}
void Client::connected() {
qDebug() << " INFO : " << QDateTime::currentDateTime() << " : CONNESSO a "
<< ip_ << " e PORTA " << port_;
//do stuff if you need
}
void Client::sendMessage(const QString& message) {
this->write(message.toUtf8());
this->write("\n"); //every message ends with a new line
}