Control ubuntu terminal from Qt C++ - c++

I want to write a routine that will automatically change my Machine learning parameters and execute the (Machine learning) code multiple times and save its result into a text file.
The Machine learning code is run from the Ubuntu terminal and its result also are written to the Ubuntu terminal.
I need a way to read data and write data to the Ubuntu terminal from the C++ code.
What I have found so far is the QProcess:
QProcess process;
process.start("gnome-terminal"); //THE TERMINAL IS OPENED INDEED
char w[] = "write";
process.write(w,sizeof(w));
process.waitForFinished();
But nothing is written or read from it
What does working is:
QProcess process1;
QProcess process2;
process1.setStandardOutputProcess(&process2);
process1.start("echo 0534230313");
process2.start("sudo -S poweroff");
process2.setProcessChannelMode(QProcess::ForwardedChannels);
And also this works:
int result = system("echo 0534230313 | sudo -S poweroff"); ///COMMANDS TO TERMINAL
int result2 = system("gnome-terminal"); ///OPEN TERMINAL
But the problem is that I wont be able to read the output result (My Machine learning program can open and write to the terminal by itself)

Use the finished signal to read the process output results
connect( poProcess, static_cast<void (QProcess::*)(int,QProcess::ExitStatus)>(&QProcess::finished),
[=](int,QProcess::ExitStatus)
{
QByteArray oProcessOutput=
poProcess->readAllStandardOutput();
// Parse the process output.
//
// Mark process for deletion.
emit poProcess->deleteLater();
});

Related

Using QProcess to read standard output

In my QT widget application I am attempting to run a shellscript that opens a C++ program and provides inputs to the program as well. The program starts a command prompt that requires the users input to start. Once the program is started the output of the program is redirected via the standard output to a text file. I am attempting to use QProcess to open and run this shellscript, then read the standard output that is being used to print the result of the C++ program to the text file. The shell script only runs this process and does not terminate it. This is because I need to continuously read this output into the GUI as the program is running. It will not be sufficient to wait until the program is finished to read this information. I am fairly new to QT and C++ programming. I was hoping that someone could help me with my implementation of this.
QProcess process;
process.start("/home/pi/Desktop/ShellScripts/RunTutorial3.sh");
QString output =process.readAllStandardOutput();
qDebug() << output;
QString err = process.readAllStandardError();
qDebug() << err;
I have experimented with using other read function such as readline and also trying to start the process as a detatched process. I have not had success with any of my experimentations. Is it possible to do what I am attempting in QT. I just need the program to run continuously and for QT to read this output every so often.
Shell script:
#!/bin/bash
cd
cd Desktop
cd tutorial3App
cd bin
echo "start" | ./tutorial3
C++ code: I need the meanTOE value to be captured in standard output to use in my GUI.
/ Calculate average time to end of discharge
double meanToE = std::accumulate(ToESamples.begin(), ToESamples.end(), 0.0)/ToESamples.size();
file << ": EOL in " << meanToE << " s" << std::endl;
As I said in my comments one of the main problems is that when you run tutorial3 that process is separated so you can not get the output. Therefore, I recommend executing it directly, and QProcess is probably a local variable, eliminating after printing an empty text, a possible solution is to create a pointer. Another improvement would be to use the readyReadStandardOutput and readyReadStandardError signals since the impressions are not automatic.
QProcess *process = new QProcess(this);
connect(process, &QProcess::readyReadStandardOutput, [process, this](){
QString output =process->readAllStandardOutput();
qDebug() << "output: "<< output;
});
connect(process, &QProcess::readyReadStandardError, [process](){
QString err = process->readAllStandardError();
qDebug() << "error: "<<err;
});
process->setWorkingDirectory("/home/pi/Desktop/tutorial3App/bin/")
process->start("tutorial3", QStringList() << "start");
I think you have to read about signals and slots in Qt. QProcess has got a signal readyReadStandardOutput. So you have to connect to this signal and in your slot you should use QProcess function readAllStandardOutput. In other words when your shell programm outputs something you catch it in your slot and dump it or whatever you want.
Check the answer on this question. It might help you.
reading and writing to QProcess in Qt Console Application

QProcess doesn't show any output when it runs rsync

I start rsync in QProcess. My process runs fine (in its own terminal) if I use QProcess::startDetached() but nothing happens if I start it with QProcess:start(). The problem seems to be that QProcess can't apparently read messages from rsync and write it to the output window.
I have connect this signal in constructor.
MainWindow::~MainWindow()
{
process = new QProcess(this);
connect( process, SIGNAL(readyReadStandardOutput()), this, SLOT(onReadyReadStandardOutput() ) );
}
Later on button clicked I call:
void MainWindow::onButton1Clicked()
{
process->start("rsync -a root#10.0.0.1:/path/ /rsync_folder");
//process->start("ping 10.0.0.01"); // this works for testing and I see output but not the above.
}
When rsync starts, it prints a message and ask for password..none of it is received by my QProcess but the ping message are received..what could be possibly wrong here?
The above grieving line also works directly on windows 7 command line but it just doesn't seem to show any progress in QProcess.
Update
Here is how I displaying the output.
void MainWindow::onReadyReadStandardOutput()
{
qDebug() << process->readAllStandardOutput();
}
http://doc.qt.io/qt-5/qprocess.html#communicating-via-channels
Did you remember to link to and check the standard error channel?
http://doc.qt.io/qt-5/qprocess.html#readAllStandardError
That has fixed it for me in the past for some QProcesses I have started.
Another way I've done it, is to use QProcess::startDetached();
Hope that helps.
My research shows that rsync probably behaves like scp which accordingly this answer doesn't generate output when it is redirected.

Qt5 Qprocess call command line program to obtain realtime output

I use QProcess to run another program. The command is airodump-ng mon0.
Its output is changing anytime, and is whole different (also not like ping command, changed by line). I want use QProcess to run that program and get its output while it is still running.
Here is the code:
pushButton_clicked()
{
myprocess = new QProcess(this);
connect(myprocess,SIGNAL(readReadStandardOutput()),this,SLOT(outlog()));
myprocess->start("sudo -A ./airodump-ng mon0");
}
outlog()
{
QString abc = myprocess->readAllStandardOutput();
textEdit->setText(abc);
}
In the program airodump-ng, I've already added code setvbuf(stdout,(char*)NULL,_IONBF,0); to use row buffering.

Executing a command shell from popen and set other command shell

I'm working in a project with a quadrotor and mavlink. I have successfully installed mavproxy in my Ubuntu PC and and ran it without problems from terminal. When I run mavproxy.py from the terminal and connected a quadrotor with support for mavlink (APM autopilot), mavproxy detects the quadrotor and everything is ok.
When you execute mavproxy.py the program in the terminal begin to send and receive several parameters. You can write in the terminal some parameter to access for any configuration. For example, the command help in the terminal:
$ mavlink.py
.
.data beging
.
STABILIZE> "when the program finish the configuration, allowed to you for doing an input any parameter, for example help"
STABILIZE>help
show all helps.
I have a code to execute mavlink.py from C++
include <iostream>
include <stdio.h>
using namespace std;
int main() {
FILE *in;
char buff[512];
if(!(in = popen("mavlink.py", "r"))){
return 1;
}
while(fgets(buff, sizeof(buff), in)!=NULL){
cout << buff;
}
pclose(in);
return 0;
}
When I run this C++ program the terminal shows the same things that would appear if I were running mavproxy.py from the terminal, but I donĀ“t know how can I send a command such as help in the C++ code.
If you read the program, the while statement allows me to capture the parameters generated from the program mavproxy.py and cout in the terminal, but mavlink.py never ends until you write something in the terminal exit or press CTRL + C so the while loop never ends.
I have been reading about the Popen function, but I haven't found the correct form to do this.
I know that I can use the mavlink.h library in my program and send parameters to the quadrotor, but don't want do this with mavlink.h.
I am not sure I understand your question, but I think you want to send commands to mavlink.py as well as read its output.
If that is the case, you must change the open mode of popen() from "r" to "w" so you can write, then you can send commands to it like this:
FILE *fp;
char *command="HELP";
if(!(fp = popen("mavlink.py", "w"))){
return 1;
fwrite(command, sizeof(char), strlen(command), fp);

How to start a Shell Script with QProcess?

How can I start a Shell Script using QProcess?
The Shell Script has eight different commands in it, some with arguments others without.
I tried to start the Shell Script with (using Ubuntu 11.10):
QProcess *Prozess = new QProcess();
Prozess->setWorkingDirectory(MainDirectory);
Prozess->start("/bin/sh", QStringList() << "Shell.sh");
But this doesn't work, that means nothing happens. How to make it work?
Code is fine. Problem is at run-time.
Either your program can't run /bin/sh for some reason (test if you can run gedit instead?), or the MainDirectory variable has wrong directory path (debug it), or the Shell.sh does not exist in that directory (capitalization mistakes? What about "./Shell.sh"?), or you don't have enough privileges to run or modify target directory/files (are they owned by you?).
The process you have started is running in background. if you want to see any explicit output from the running script you have to connect to void readyReadStandardOutput() or/and void readyReadStandardError() and read from the process explicitly. For example:
void onReadyRead() {
QByteArray processOutput = Prozess->readAllStandardOutput();
}
This should work:
QProcess::ProcessError Error = myProcess->readAllStandardError();
return Error;
QProcess ().execute ("/bin/sh " + MainDirectory + "/Shell.sh");
will do the job.