Pinging with Yun

Hi,

The code below pings www.google.com and works but I don’t like the way I’ve done it. Is there a better and shorter way to do it?

TIA

#include 

String pingOut = "";
String pingString = "";
bool gotPing = false;

void setup() {
  Bridge.begin();  // Initialize the Bridge
  Console.begin(); // Initialize the Serial

  // Wait until a Serial Monitor is connected.
  while (!Console);
}

void loop() {

  if (pingGoogle())Console.println("Internet up");
  else Console.println("Internet down");

  delay(5000);  // wait 5 seconds before you do it again
}

bool pingGoogle() {
  Process p;

  p.runShellCommand("/mnt/sda1/test.sh");   //file containing ping cmd

  // do nothing until the process finishes, so you get the whole output:
  while (p.running());

  // Read command output
  while (p.available()) {
    char c = p.read();
    pingOut += c; // my case => 64 bytes from 216.58.212.164: seq=0 ttl=51 time=35.405 ms

    if (pingOut.endsWith("seq=")) {
      gotPing = true;
    }
    else if (gotPing) {
      if (!pingOut.endsWith("time=")) {
        pingString += c;
      }
      else {
        gotPing = false;
        pingString.trim();
      }
    }
//    int test = pingString.substring(6, 8).toInt();  //my case => 51
//    Console.println(test, DEC);
  }
  if (pingString.substring(6, 8).toInt() > 0) return true;
  else return false;
}

I would be inclined to make your test.sh script do more, and the sketch do less.

Write the sketch so it sends the pings and parses the results, and makes the determination whether the remote system responded or not. For example, run the ping command, and pipe the output to grep with an appropriate regular expression that matches only a valid response. Use the "-q" option of grep to return only 0 (match) or 1 (no match) and test that return value, printing a simple response like Y/N, T/F, 1/0, or something like that.

An example of such a command:

ping -c 3 google.com | grep -q "seq=.* time=" && echo "Y" || echo "N"

This command line first runs ping, sending three requests to google.com. The output of that command is piped to the grep command, which uses the -q option to suppress all output and only return 0 if there was a match, and 1 if there was no match. The regular expression looks for any line that contains "seq=" followed by " time=" with any number of any characters between them. The "&&" and "||" operators check the return value of grep, and will echo "Y" if the return value is zero (a match) or "N" if the return value is anything else (no match.)

The sketch can then run that command script, and it only needs to read and check one character to determine whether the remote system is up or not. When using Process.runShellCommand(), it's good to know that it's a blocking command - it doesn't return until the command is complete. That means that it's not necessary to wait for the process to finish - by the time the function returns, the process is already finished.

The pingGoogle() function that calls this script could look like:

bool pingGoogle() {
  Process p;

  p.runShellCommand("/mnt/sda1/test.sh");   //file containing ping cmd
  return (p.read() == "Y");
}

This highly shortened function takes advantage of the fact that runShellCommand() is blocking, so there is no need to wait for it. It also assumes that the first (and actually the only) character that is returned gives the meaningful information. Therefore, there is no need to loop while p.available() is true, nor is there a need to check all of the data. p.read() will return the first available character, and if that character is "Y" the function will return true, else it will return false. On the chance that nothing at all was returned by the process, read() will return -1, which is not equal to "Y", so the pingGoogle() function will return false.

It worded beautifully. Thank you much!!

#include 

void setup() {
  Bridge.begin();  // Initialize the Bridge
  Console.begin(); // Initialize the Serial
  delay(100);
  while (!Console); // Wait until a Serial Monitor is connected.
}

void loop() {
  if (pingGoogle())Console.println("Internet is up");
  else Console.println("Internet is down");
  delay(5000);  // wait 5 seconds before you do it again
}

bool pingGoogle() {
  Process p;
  p.runShellCommand("/mnt/sda1/pingGoogle.sh");   //file containing ping command
  return (p.read() == 'Y');
}