Fastest way to communicate with the Linux side

Hi,

I need some help on how to pull (or push) data from the Linux side.

I have a php-script that fetches an integer from a database and echoes it back. Right now the code on the Arduino look like this:

Process p;
p.begin("/mnt/sda1/getInt.php");
p.addParameter(String(myString));
p.run();
while (p.available() > 0) {
    fetchedInt = p.parseInt();
}

This works perfectly fine, but it takes about 3 seconds for every fetch, and the Arduino is of course unresponsive in this period.

I have looked into runShellCommandAsynchronously(), but as I understand it, it is not possible to make a call back and thereby get a return when there is one ready.

What can I do to optimize the communication?

Id use bridge in an asynchronus way, so you can still do some tasks during those 3 seconds. This can be done on a python script because the library is for python, using bridge.put and bridge.get you can monitor a trigger, and when the trigger changea use bridge.get to receive data.

I think the fetching is going to take 3 seconds anyway because of the resources of the Yun, 64 mb ram and 400 mhz. Ive fetched info from very small databases on the linux side even using sqlite and it took some seconds to retrieve data using a python code.

Do you know if the same thing can in any way be accomplished in php? If not, I will have to learn python :slight_smile:

The fetching can take as long as it have to, as long as the system is still responsive in the period.

SomethingClever:
I have looked into runShellCommandAsynchronously(), but as I understand it, it is not possible to make a call back and thereby get a return when there is one ready.

Try this: define your Process object at the global file level, not in loop(). Start your process asynchronously, but don’t put in a while loop to wait for a response. Instead, in loop(), make a call to p.available() in an if statement: if characters are available, read them and append them to a a String or character buffer. When you get an appropriate delimiter (perhaps a newline character?) then process the data in the buffer.

Basically, you never want to use while… you need to use non-blocking code. Robin2 has a good thread discussing some appropriate techniques: Serial Input Basics. Those techniques are directly applicable here: wherever he makes reference to Serial, you can directly substitute your process object, since they both derive from the same underlying Stream class. The only part that isn’t the same is creating the object - instead of calling Serial.begin() you will create the process object and set the parameters, then call runAsynchronously.

SomethingClever:
...
This works perfectly fine, but it takes about 3 seconds for every fetch, and the Arduino is of course unresponsive in this period.
...

Php and Sqlite3 profile speed is 4.35 ms

4.35 ms v.s. 3000 ms? You might need profile your database and php.

As ShapeShifter said, you can start the process asinchronously and then periodically check if the process ended.

Remember you can use Process.running() to check if it ended or not:
https://www.arduino.cc/en/Reference/YunProcessRunning

Thanks guys, I will look into it over the weekend.

@sunnyyu

Yeah, it seems weird that it is so slow, but I have no problems with the DB for other uses.

I finally had the time to look into this, and followed the examples from Robin2. I didn't even had to run the process asynchronously.
The culprits were the while statement and the parseInt().

This works like a charm in my test code:

Process p;
char receiveData[1];

---

void getData() {
    p.begin("/mnt/sda1/getInt.php");
    p.addParameter(String(myString));
    p.run();
    if(p.available() > 0) {
      receiveData[0] = p.read();
    }
    int i = atoi (receiveData);
}

Thanks for the help everyone!