0

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:

  1. How can I keep th GUI responsive after runSensorStartProcess starts?
  2. How can I stop that process on demand (in fact by starting runSensorStartProcess)?
  3. Do I need a separate thread for runSensorStartProcess?
QuestionMark
  • 412
  • 1
  • 4
  • 16
  • You need to provide more information. Are `start` and `stop` applications in their own right or are they command line options or subcommands for the `runSensor` application? Specifically, if you were looking at the command prompt in a console what you you type to start the data acquisition and what would the response be at the console? – G.M. May 30 '17 at 15:05
  • @G.M. `start` and `stop` are subcommands of `runSensor`. The was I call `start` in the above snippet, `this->socketHandler` recieves the data from sensor and logs it in a txt file. So, I am sure that `runSensor` app is running in the background. I cann't only stop it via **GUI** since it freezes. – QuestionMark May 30 '17 at 15:12
  • You haven't completely answered the question though. What would you type at a command prompt and what output -- if any -- would you then expect to see? If you could edit your post to show a sample terminal session that would probably help. – G.M. May 30 '17 at 15:19
  • @G.M. Sample output included in the question. – QuestionMark May 30 '17 at 15:32

1 Answers1

1
  1. 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.

  2. Aren't QProcess::kill and QProcess::terminate what you need?

  3. Never. See also answer 1 and answer 2.

Community
  • 1
  • 1
Kuba hasn't forgotten Monica
  • 95,931
  • 16
  • 151
  • 313
  • The catch is, as soon as `runSensorStartProcess` starts, the GUI is frozen andI cannot interact with it. So, there is no way to call `QProcess::terminate`. I am thinking of a solution in the line of using the `runSensorStartProcess` in a `QThread`. Is it sound to you? – QuestionMark May 31 '17 at 06:54
  • As you may noted, `runSensorStartProcess` never finishes since it reads realtime sensor data stream. I need a second process to tell the sensor to `stop` transmission (which allows the first process to be finished). But to start the second process I should be able to click a button! – QuestionMark May 31 '17 at 07:07
  • The only long-time-running loop in the main thread should be this one: `app.exec()` in `main()`. To process sensor data you should be reacting to `QProcess`'s `readyRead` signal. **Under no circumstances you should loop anywhere waiting for data!**. – Kuba hasn't forgotten Monica May 31 '17 at 12:41
  • I am not waiting anwhere for data. Indeed, I wait for readyRead signal to be fired. I've also removed all `waitForXxx` instances from the code. – QuestionMark May 31 '17 at 13:03
  • You don't show nearly enough code to confirm that what you say is true. Please post a complete example. – Kuba hasn't forgotten Monica May 31 '17 at 13:06