Receiving data from a Webpage

Hi,

What would be the easiest approach for receiving data on an Arduino from a Webpage ?
Basically I want to send ‘button-press’ events and perhaps a ‘textbox-value’ to the Arduino.

PS.
Arduino is connected to the internet through WiFi Shield.
Im able to run client / cerver code.

Best regards

What would be the easiest approach for receiving data on an Arduino from a Webpage ?

If the web page is not served by the Arduino, it is going to be a lot more challenging to make the action events make requests to the Arduino-as-server.

If the Arduino is the server, then the process should be pretty obvious. The Arduino is already (or should be) determining what the client requested. Adding some if-the-client-request-includes blocks is trivial.

If the Arduino is the server, and you are blindly serving up the same page regardless of what the client asked for, then you need to stop that.

One of the requirements for posting in the Programming section is to post your code. You failed to do that.

Well, if I know the ip address of the Arduino (and I do), and the Arduino is listening for clients, wouldn't it then be possible to send simple data directly to it ?

How do I do that ?

Yes, I failed - like so many before ;-)

and the Arduino is listening for clients, wouldn't it then be possible to send simple data directly to it ?

Yes, it is. But the "simple data" is in the form of a GET request.

How do I do that ?

You start by posting your code.

A failing grade on a test doesn't mean that you skip the makeup test or that you have to fail that, too!

Well "ace" - that's the point - I have no code, if I had I would ask "why doesn't this work" !? Instead I'm asking how is it done, that would somehow indicate that im on "thin ice", or ... ?

But here is a piece of code, are you happy now ?

// listen for incoming clients WiFiClient w_client = w_server.available(); if (w_client) { if (w_client.connected()) { while(w_client.available() > 0) { char c = client.read(); Serial.write(c); } Serial.println("Connected to client"); } // close the connection: Serial.println("Disconnected"); w_client.flush(); w_client.stop(); }

       char c = client.read();
Serial.write(c);

What does this show you? It is what the client requested.

You can't begin to parse a client request until you know what you are parsing.

When you know what the client is requesting, you can write code to satisfy that request.

Well, if I know the ip address of the Arduino (and I do), and the Arduino is listening for clients, wouldn’t it then be possible to send simple data directly to it ?

Yes. Bottom is some simple server test that has a submit box where you can enter values. You use the serial monitor to see what is being received by the server. Below is how you would incorporate sending the submit request to an arduino IP address different from where the page itself is served from.

client.println("<FORM ACTION='http://192.168.1.102:84/' method=get >"); //uses IP/port of the arduino server
//zoomkat 12-08-12
//get submit box code
//for use with IDE 1.0
//open serial monitor to see what the arduino receives
//use the \ slash to escape the " in the html or use a '
//address will look like http://192.168.1.102:84 when submited
//for use with W5100 based ethernet shields
//note that the below bug fix may be required
// http://code.google.com/p/arduino/issues/detail?id=605 

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

byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }; //physical mac address
byte ip[] = { 192, 168, 1, 102 }; // 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(5, 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("server text box test1"); // 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); //see what was captured

          //now output HTML data header

          client.println("HTTP/1.1 200 OK");
          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>HTML form GET example</H1>");

          client.println("<FORM ACTION='/' method=get >"); //uses IP/port of web page

          client.println("Pin 5 'on5' or 'off5': <INPUT TYPE=TEXT NAME='LED' VALUE='' SIZE='25' MAXLENGTH='50'>
");

          client.println("<INPUT TYPE=SUBMIT NAME='submit' VALUE='Change Pin 5!'>");

          client.println("</FORM>");

          client.println("
");

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

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

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

        }
      }
    }
  }
}

Hi,

Thanks zoomkat, I understand this.

What I have is a webpage where some data are displayed. The arduino sends these data to the webserver, and data are read / displayed by a php script. What I would like was, to be able to push a button on the webpage and based on that, send some command to the arduino. Eg. Stop / Start logging.

Can this be done in a very simple way ?, or do I need to pars the html code sent to the arduino, and search for specific chars in a string. To me that sound a little unreliable ;-) ?

Also - I dont really want the arduino to send back all this html stuff, as this is already handled by the webserver. Does the webserver expect and answer, and what is the bare minimum I can return to satisfy it ?

Best regards

What I have is a webpage where some data are displayed. The arduino sends these data to the webserver, and data are read / displayed by a php script.

That is NOT what the code you posted does.

Either post your real code or go away.

A client, as you are describing the Arduino above, can NOT be contacted by another client (the web browser) under any circumstances. The server that is in between can NOT push data to a client.

In response to a pull request (a GET, PUT, or POST), the server generates a response which is sent back to the client, and then the server looses all ability to remember that that client ever even existed, and has no way to get in touch with that client again.

All connections to a server that appear to be persistent, like online shopping carts, are because the client remembers where the server is, how to get in touch with it, and the credentials needed by the server to make it appear to be a persistent connection (like session ID).

PaulS: That is NOT what the code you posted does.

Either post your real code or go away.

Dont tell me to go away ! I dont know you, you dont know me. Just because you're behind a screen, doesn't mean you can behave like this. If this is as constructive as you can get - well then shut up. And you go away.

Nevertheless I'm not quite sure you're right. I have seen examples where arduino is running both as server and client. So somehow it must be possible.

I have seen examples where arduino is running both as server and client. So somehow it must be possible.

It is possible for a machine to be both client and server. It is not possible for one client to talk to another client. It is not possible for a server to initiate communications with a client.

So, there is no way for a web browser to PUSH information to another client. The web browser can make GET requests that cause a server to do something. If the server is the Arduino, the Arduino can respond to those requests by returning data, or by turning LEDs on.

However, it is VERY unusual for a server to serve up pages containing forms with submit buttons where the submit button causes a GET request to be made to a different server.

Why is it so difficult for the Arduino to be a server in your case?

OK - thank you for the explanation.

What I have is this (a some more code, with other functionality).

void SendDataToWeb(void)
{
  char buffer[25];
  char url[] = "http://www.mywebserver.dk/arduino/arduino_update_data.php?";

  status = client.connect(df_server, 80);
  if (status)
  {
    client.print(("GET "));
    client.print(url);

    sprintf(buffer, "CHN0=%d&CHN1=%d&CHN2=%d&CHN3=%d", chn0_t, chn1_t, chn2_t, chn3_t);
    client.print(buffer);

    client.println((" HTTP/1.1"));
    client.println(("Host: www.mywebserver.dk"));

    client.println(("Connection: close"));
    client.println();

    client_close_cnt = 30;  //close after 30 x 100 ms = 3 sec
  }
  else
  {
    nLCDUpdate(NO_LCD_CMD, 19, 0, TXT_DATA_INDICATOR_ERR, NULL);
    client.stop();
  }
}

4 analogue channels are read every 5 sec. Values are transmitted to webserver. The "arduino_update_data.php" script grabs the data and saves them in a .csv file. Asynch to this, when a user opens the webpage, a second .php script generates a graph, reads data from .csv files and shows them in the graph. Buttons for clearing data etc. are also generated and shown.

Everything works like a charm :-)

Now what I would like to have, was a button where I could trigger functionality in the Arduino, like Start / Stop the logging etc.

Any inputs on how this could be done ?

You must read and parse the response from the server. This will display it on the serial monitor.

    client.println(("Connection: close"));
    client.println();
    while(client.connected()) {
        while(client.available()) {
            char ch = client.read();
            Serial.write(ch);
        }
    }
    client.stop();

That is the "Perfect World" code, but it should display the server response if the server doesn't stall and the connection doesn't fail.

edit: Here is a link to my example sketch on the playground. It has all the error checking and fault tolerance to make it "Real World" compatible.

Now what I would like to have, was a button where I could trigger functionality in the Arduino, like Start / Stop the logging etc.

Below is some simple server code that serves a web page with simple click commands. The GET request from the client is evaluated by the server and actions performed based on the command contents. The server return to the client includes the status: 204 code telling the client to not refresh the web page.

//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");
               client.println();
               client.println();  
             }
             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="";

        }
      }
    }
  }
}

OK - thanks. I understand this.

But what I do not understand is where to host my graph code stuff etc. ? Not in the Arduino, or ?

Regards