c++qttcpclientqthreadqtcpsocket

How to pass user input form the console to an object in a diffrent thread -> QTcpsocket


I am trying to create an Application that lets the user input an integer value and then sends it via tcp to my esp32.

I have set up my esp32 as a tcp server which connects to my wifi router and than shows its ipv4 adress via serial Monitor. The esp32 is connected to 2 stepperdriver and shall later control them with the data from the Application.

So my Application is working when the data that has to be sent is known before runtime for example i could create a const char* variable with the desired data and then simply send it with socket->write(foo);.

But thats not working for me because i need to get input from the console at runtime and then pass it to the function socket->write(). The problem there is that the QTcpSocket Object has to be in another thread. So i am stuck at figuring out how to pass data in between threads.

I tried to use the signal and slot mechanism to do so which if i correctly understood is meant to be used for that.

Especially this line gives me a huge headache. (the line is in the main function) emit IO->doSendData(IO->getInput());

I try to emit the signal doSendData and pass the input from the console to the connected slot sendData() which is a method from the network class which object is in the threadNET and the object thats getting the input from the console lives in the main thread i guess thats the problem here but i have no glue how to fix it. I dont get any error messages in QTcreator.

Thanks in advance for taking your time to help me. If something is unclear feel free to ask me anything. Thats my first post on Stack overflow and i would appreciate any feedback on how to increase the quality of my question.

Complete code

main.cpp

//MAIN

#include <QCoreApplication>
#include <network.h>
#include <userio.h>
#include <QThread>

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);


    QThread* threadNET = new QThread();

    network* net = new network();
    userIO* IO = new userIO();

    net->moveToThread(threadNET);


    QObject::connect(threadNET,
                     &QThread::started,
                     net,
                     &network::Connect);


    QObject::connect(IO,
                     &userIO::doSendData,
                     net,
                     &network::sendData);


    threadNET->start();

    while(true)
    {
    emit IO->doSendData(IO->getInput());
    }

    return a.exec();
}

network.h

//NETWORK HEADER

#ifndef NETWORK_H
#define NETWORK_H

#include <QObject>
#include <QTcpSocket>
#include <QAbstractSocket>
#include <QString>
#include <QDebug>
#include <iostream>
#include <string>

class network : public QObject
{
    Q_OBJECT
public:
    explicit network(QObject *parent = nullptr);
    ~network();

signals:
    void finished(QString ffs);
    void error(QString err);

public slots:
    void Connect();
    void sendData(QString dataToSend);

private:
    QTcpSocket *socket;
};
#endif // NETWORK_H

userIO.h

//USERIO HEADER

#ifndef USERIO_H
#define USERIO_H

#include <QObject>
#include <QString>
#include <iostream>
#include <QDebug>
#include <limits>
#include <string>

class userIO : public QObject
{
    Q_OBJECT
public:
    explicit userIO(QObject *parent = nullptr);
    QString getInput();
signals:
void doSendData(QString dataToSend);

public slots:
};

#endif // USERIO_H

network.cpp

//NETWORK SOURCE

#include "network.h"

network::network(QObject *parent) : QObject(parent)
{

}

network::~network()
{

}

void network::Connect()
{
     socket = new QTcpSocket(this);

     socket->connectToHost("192.168.179.167", 80);

     if(socket->waitForConnected(5000))
     {
         std::cout << "Connected to TcpServer";
     }
     else
     {
         qDebug() << "Error: " << socket->errorString();
     }
     emit finished("send help");
}

void network::sendData(QString dataToSend)
{
    qDebug() << "sendData" << dataToSend << "\n";

    std::string convert = dataToSend.toStdString();
    const char* formattedData = convert.c_str();

    socket->write(formattedData);
}

userIO.cpp

//USERIO SOURCE

#include "userio.h"

userIO::userIO(QObject *parent) : QObject(parent)
{

}

QString userIO::getInput()
{

    std::string rawInput;

    qDebug() << "Enter the amount of steps to go\n";
    std::cin >> rawInput;

    while(std::cin.fail())
    {
        qDebug() << "Invalid input only Integer numbers are allowed\n";
        qDebug() << "try again...\n";
        std::cin.clear();
        std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
        std::cin >> rawInput;
    }

    QString convert;
    convert.fromStdString(rawInput);
    return convert;
}


Solution

  • QString::fromStdString(const std::string &str) is a static member that returns a copy of the str string.

    calling convert.fromStdString(rawInput); does not store copied string in convert !!

    you need to write :

    convert = QString::fromStdString(rawInput)
    

    OR direct initialization:

    ...
    QString convert(QString::fromStdString(rawInput));
    return convert;