Yun - Parsing incoming URL for string

I did the google search and forum, but I found more on char and integers. Sorry if I missed the answer - So, I will follow any links if already a commonly answered question.

I stripped the Bridge example for what I needed. But, for some reason when I send the following URLs to the Yun they are caught by the “error” lines and printed to the client. I’m sure it’s something incredibly simple that is eluding me:

#include <Bridge.h>
#include <YunServer.h>
#include <YunClient.h>

YunServer server;

void setup() {
  Serial.begin(9600);
  pinMode(13,OUTPUT);
  digitalWrite(13, LOW);
  Bridge.begin();
  server.listenOnLocalhost();
  server.begin();
}

void loop() {
  YunClient client = server.accept();

  if (client) {
    process(client);
    client.stop();
  }

  delay(50); 
}

void process(YunClient client) {
  String command = client.readStringUntil('/');

  if (command == "open") {
    digitalWrite(13,1);
    
  }
  if (command == "close") {
    digitalWrite(13,0);
  }
  
  if (client.read() != '/') {
    client.println(F("error"));
    client.println(command); // DEBUG
    return;
  }
}

When I send:

http://192.168.32.57/arduino/open

LED 13 will not turn on and I get this on my browser:

error
open

A matter of fact, whatever I send after the “…arduino/” is caught by error and printed. The example/bridge code works as expected.

Any guidance would be very helpful and welcome. I just want to use this to add a wireless trigger for a functioning project/sketch.

Thank you!

  String command = client.readStringUntil('/');

Why do you assume that the / is left in the buffer?

Have you actually looked at the code and determined that it is?

Well, honestly, I’m not sure. When the client.println(command); came back with what I expected, I assumed that wasn’t the issue. Same is true if I send “open/”

I figured I wanted a some sort of terminator versus letting readString timeout (per the doc).
… tried replacing without the terminator, and tried to clear anything in buffer… got the same result.

Edits from orig post:

#include <Bridge.h>
#include <YunServer.h>
#include <YunClient.h>

YunServer server;

void setup() {
  Serial.begin(9600);
  pinMode(13,OUTPUT);
  digitalWrite(13, LOW);
  Bridge.begin();
  server.listenOnLocalhost();
  server.begin();
}

void loop() {
  YunClient client = server.accept();

  if (client) {
    process(client);
    client.stop();
  }

  delay(50); 
}

void process(YunClient client) {
//  String command = client.readStringUntil('/');
  String command = client.readString();  

  if (command == "open") {
    digitalWrite(13,1);
    
  }
  if (command == "close") {
    digitalWrite(13,0);
  }
  
  if (client.read() != '/') {
    client.println(F("error"));
    client.println(command); // DEBUG
    return;
  }
  command = "";  //DEBUG try clearing buffer???
}

Thank you for replying - I’m still in same situation, but probably because I don’t understand the tip.

I figured I wanted a some sort of terminator versus letting readString timeout (per the doc). .... tried replacing without the terminator, and tried to clear anything in buffer.... got the same result.

Store the value read in a variable. Print the value in the variable. Then, test the variable. What IS the next character?

I thought that is what I am doing with the following lines:

 String command = client.readStringUntil('/'); // write string to variable "command" 
 client.println(command); // DEBUG  // Print the result back to browser

The only thing I am sending is:

http://192.168.32.57/arduino/open

and I get "open" back on the browser. Sorry if I dont understand, maybe your are telling me there is some conversion or translation going in storing of the variables. maybe I didn't grasp that lesson completely. I'll go back and reread docs on strings and variables. It seems to work fine in the example sketch.

I appreciate your help.

Updated to add clarity:

Using the code below, when I send the URL “http://192.168.32.57/arduino/open/” to the Yun. I get “open” printed on my browser, but pin/LED 13 will not turn on.

#include <Bridge.h>
#include <YunServer.h>
#include <YunClient.h>

YunServer server;

void setup() {
  Serial.begin(9600);
  pinMode(13,OUTPUT);
  digitalWrite(13, LOW);
  Bridge.begin();
  server.listenOnLocalhost();
  server.begin();
}

void loop() {
  YunClient client = server.accept();

  if (client) {
    process(client);
    client.stop();
  }

  delay(50); 
}

void process(YunClient client) {
  String command = client.readStringUntil('/');
  

  if (command == "open") {
    digitalWrite(13,1);
    
  }
  if (command == "close") {
    digitalWrite(13,0);
  }
  
//  if (client.read() != '/') {
//    client.println(F("error"));
//    client.println(command); // DEBUG
//    return;
//  }
client.println(command); // DEBUG
  command = "";
}

I just want to make sure the “/” limiter and URL I sent was clear.

Thanks

but pin/LED 13 will not turn on

I don't know about a yun, but on an arduino pin 13 with the LED is a timing pin used by the ethernet shield. This prevents it from being used for anything else. Is your pin 13 very dimly lit?

//  if (client.read() != '/') {
//    client.println(F("error"));
//    client.println(command); // DEBUG
//    return;
//  }

How about:

char afterReadingString = client.read();
Serial.print("After reading the String, the next char is [");
Serial.print(afterReadingString);
Serial.println("]");
if(afterReadingString == '/')

Then, you would KNOW, not need to guess, whether the / was left in the buffer, or not.

PaulS,

I will give that a shot and report back.

Before I walked away. I tried to post the following:

Ok,

It works as expected if I add anything after the "open/" and "close/"

For example, URL: http://192.168.32.57/arduino/open/blah

Turns on the LED with "open" the browser.

...and

http://192.168.32.57/arduino/close/blah

Turns off the LED..

Ah, this makes perfect sense to you folks.. I am still pondering. Maybe the readUntil "/"

PaulS,

This is what I have after adding your code:

When I send " http://192.168.32.57/arduino/open" or "http://192.168.32.57/arduino/open/" I get:

After reading the String, the next char is [ÿ]

LED does not come on.

If I send "http://192.168.32.57/arduino/open/junk" I get:

After reading the String, the next char is [j]

And the LED comes on. The "close/" works similarly (turns off with first char after "/" showing)

I understand why the terminator is used, but not sure why I need a char after the "/" to function as expected. Moreover, I thought readStringUntil('/'); would NOT included the "/" - Seemed like the "/" would be the next char.

Thanks - I know I missing a key fundamental concept here.

zoomkat,

Thanks for asking. pin 13 as a LED seems to work as expected on the Yun.

All/PaulS,

Looks like I made another Noob mistake by not telling exactly what I want. I have a sketch that works fine for activating a linear actuator w/ buttons on the arduino and a IR remote. I want to add WiFi via a URL get request to the Yun. I want to send "open" to turn the pin HIGH to start the actuator.

The example code I am using from Bridge may not be what I want based on feedback and the actions.

I want to send "http://192.168.32.57/arduino/open" to set pin 13 HIGH and "http://192.168.32.57/arduino/close" to set pin 13 LOW.

Thinking out loud, but maybe something like TextFinder or string subString?

Some simple arduino server code.

//zoomkat 10-6-13
//simple button GET with iframe code
//open serial monitor to see what the arduino receives
//use the ' instead of " in html ilnes 
//address will look like http://192.168.1.102:84/ when submited
//for use with W5100 based ethernet shields

#include <SPI.h>
#include <Ethernet.h>

byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }; //ethernet shield mac address
byte ip[] = { 192, 168, 1, 102 }; // arduino IP in lan
byte gateway[] = { 192, 168, 1, 1 }; // internet access via router
byte subnet[] = { 255, 255, 255, 0 }; //subnet mask
EthernetServer server(84); //server port

String readString; 

//////////////////////

void setup(){

  pinMode(4, OUTPUT); //pin selected to control
  //start Ethernet
  Ethernet.begin(mac, ip, gateway, gateway, subnet);
  server.begin();

  //enable serial data print 
  Serial.begin(9600); 
  Serial.println("servertest1"); // so I can keep track of what is loaded
}

void loop(){
  // Create a client connection
  EthernetClient client = server.available();
  if (client) {
    while (client.connected()) {
      if (client.available()) {
        char c = client.read();

        //read char by char HTTP request
        if (readString.length() < 100) {

          //store characters to string 
          readString += c; 
          //Serial.print(c);
        } 

        //if HTTP request has ended
        if (c == '\n') {

          ///////////////
          Serial.println(readString); //print to serial monitor for debuging 

          //now output HTML data header
             if(readString.indexOf('?') >=0) { //don't send new page
               client.println("HTTP/1.1 204 Zoomkat\r\n\r\n");
             }
             else {
          client.println("HTTP/1.1 200 OK"); //send new page
          client.println("Content-Type: text/html");
          client.println();

          client.println("<HTML>");
          client.println("<HEAD>");
          client.println("<TITLE>Arduino GET test page</TITLE>");
          client.println("</HEAD>");
          client.println("<BODY>");

          client.println("<H1>Zoomkat's simple Arduino button</H1>");
          
          client.println("<a href='/?on1' target='inlineframe'>ON</a>"); 
          client.println("<a href='/?off' target='inlineframe'>OFF</a>"); 

          client.println("<IFRAME name=inlineframe style='display:none'>");          
          client.println("</IFRAME>");

          client.println("</BODY>");
          client.println("</HTML>");
             }

          delay(1);
          //stopping client
          client.stop();

          ///////////////////// control arduino pin
          if(readString.indexOf("on1") >0)//checks for on
          {
            digitalWrite(4, HIGH);    // set pin 4 high
            Serial.println("Led On");
          }
          if(readString.indexOf("off") >0)//checks for off
          {
            digitalWrite(4, LOW);    // set pin 4 low
            Serial.println("Led Off");
          }
          //clearing string for next read
          readString="";

        }
      }
    }
  }
}

ArdNoob: ::::SNIP::::

When I send:

http://192.168.32.57/arduino/open

LED 13 will not turn on and I get this on my browser:

error
open

A matter of fact, whatever I send after the "...arduino/" is caught by error and printed. The example/bridge code works as expected.

Any guidance would be very helpful and welcome. I just want to use this to add a wireless trigger for a functioning project/sketch.

Thank you!

@ArdNoob,

the bridge library on the Linux side is written in python. When you issue an open or close, you are using python keywords. This is confusing the pyton interpreter. Use different words, like on and off, in your REST API.

Jesse

Thanks PaulS, Jesse and Zoomkat,

After pondering what some of you suggested and a little more reading, I got the following to work as expected.

#include <Bridge.h>
#include <YunServer.h>
#include <YunClient.h>

String command;

YunServer server;

void setup() {
  Serial.begin(9600);
  pinMode(13,OUTPUT);
  digitalWrite(13, LOW);
  Bridge.begin();
  server.listenOnLocalhost();
  server.begin();
  delay(3000);
  Serial.println("Server is Ready"); // Debug
}

void loop() {
  YunClient client = server.accept();

  if (client) {
    process(client);
    client.stop();
  }

  delay(50); 
}

void process(YunClient client) {

  String command = client.readStringUntil('\r');

  if (command.substring(0) == "open") {
    digitalWrite(13,1);
    Serial.println("open found");
  }
  
  if (command.substring(0) == ("close")) {
    digitalWrite(13,0);
    Serial.println("close found");
  }
  // DEBUG
  Serial.print("This was sent [");
    Serial.print(command);
    Serial.println("]");
  
  // Clearing string for next read
  command = "";
}

Now, I realize any URL sent with “open” || “close” will trigger it, but I can change it to something like “openSaysMe” or something silly/odd. If there are any pointers/suggestions on where to clean this up, I am open to it. I feel like I hacked up something but using the substring without a range, but still learning.

Thanks - I really do appreciate the pointers and the time you took to reply.