Read a HTTP response from PHP

Hello i'm trying to make a script that sends data to a php page and then receives a response.
The idea is that the data send from the arduino is checked by the php page and the page then sends back either a 0 or a 1.

However I have trouble with reading and using the 0 or 1 that is send back from the php page.
For now I wan't to use the 0 or 1 that is send back in an if statement but the response is much more then just the 0 or 1.
Can anyone give me a solution or advice on how I can do this?

Arduino code

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

byte mac[] = { 0x90,0xA2,0xDA,0x00,0x55,0x8D};
EthernetClient client;


void setup()
{
  Serial.begin(9600);
  Ethernet.begin(mac);
  delay(1000);
  Serial.println("connecting...");
  
  pinMode(7, OUTPUT);
  
  String data;
  data+="";
  data+="data=1234";
  data+="&submit=Submit"; // Submitting data
  
  if (client.connect("192.168.107.222",80)) 
  {
    Serial.println("connected");
    client.println("POST /pin/abovePage.php HTTP/1.1");
    client.println("Host: 192.168.107.222");
    client.println("Content-Type: application/x-www-form-urlencoded");
    client.println("Connection: close");
    client.print("Content-Length: ");
    client.println(data.length());
    client.println();
    client.print(data);
    client.println();
    
    //Prints your post request out for debugging
    Serial.println("POST /pin/abovePage.php HTTP/1.1");
    Serial.println("Host: 192.168.107.222");
    Serial.println("Content-Type: application/x-www-form-urlencoded");
    Serial.println("Connection: close");
    Serial.print("Content-Length: ");
    Serial.println(data.length());
    Serial.println();
    Serial.print(data);
    Serial.println();
  }
  delay(2000);
  Serial.println("Response: ");
}

void loop()
{  
  if (client.available()) 
  {
    char c = client.read();
    Serial.println(c);
  }
}

This is the output when the code is executed:
HTTP/1.1 200 OK DATE: Thu, 27 Feb 2014 09:24:23 GMT Server: Apache/2.2.22 (Win32) PHP/5.4.3 X-Powerd-By: PHP/5.4.3 Cache-Control: no-cache, must-revalidate Expires: Sat, 26 Jul 1997 05:00:00 GMT Content-Length: 1 Connection: close Content-Type: text/html 1

PHP code, I plan on using a database connection to check the data later but this is the basic idea.

<?php

header("Cache-Control: no-cache, must-revalidate"); // HTTP/1.1
header("Expires: Sat, 26 Jul 1997 05:00:00 GMT"); // Date in the past
header("Content-type: text/html");

$data = $_POST["data"];

switch ($data) 
{
	case '1234':
		echo('1'); 
		break;
	default:
		echo('0');
		break;
}

?>

Source: Arduino – HTTP Post Requests | Protoneer.co.nz

This is the output when the code is executed:

No, it isn't. The carriage returns and line feed that you stripped out are important.

You should work on your PHP script so that it returns more than 0 or 1. Something like "TheImportantValue = 0" would be far easier to extract the important value from.

Or maybe "Access allowed" vs. "Access denied".

Something like "TheImportantValue = 0" would be far easier to extract the important value from.

Thank you for your reply I will give that a try.

Hi, i want to make a project that exactly the same with coolenab. But, unfortunately i'm also figuring out the same problem which is i don't get the only character i want, but i also get HTTP Response message. Here is the data i get from serial monitor :

My IP address: 192.168.0.16.
connecting...
connected
POST /CilsyProject/tstarduino2.php HTTP/1.1
Host: 192.168.0.14
Content-Type: application/x-www-form-urlencoded
Connection: close
Content-Length: 23

data=1234&submit=Submit
Response: 
HTTP/1.1 200 OK
Date: Fri, 06 Mar 2015 12:30:17 GMT
Server: Apache/2.4.7 (Ubuntu)
X-Powered-By: PHP/5.5.9-1ubuntu4.6
Cache-Control: no-cache, must-revalidate
Expires: Sat, 26 Jul 1997 05:00:00 GMT
Content-Length: 16
Connection: close
Content-Type: text/html

CorrectAdmin = 1

The character that i only want is : CorrectAdmin = 1. But i also get :

HTTP/1.1 200 OK
Date: Fri, 06 Mar 2015 12:30:17 GMT
Server: Apache/2.4.7 (Ubuntu)
X-Powered-By: PHP/5.5.9-1ubuntu4.6
Cache-Control: no-cache, must-revalidate
Expires: Sat, 26 Jul 1997 05:00:00 GMT
Content-Length: 16
Connection: close
Content-Type: text/html

This is my arduino sketch :

/*
  DHCP-based IP printer
 
 This sketch uses the DHCP extensions to the Ethernet library
 to get an IP address via DHCP and print the address obtained.
 using an Arduino Wiznet Ethernet shield. 
 
 Circuit:
 * Ethernet shield attached to pins 10, 11, 12, 13
 
 created 12 April 2011
 modified 9 Apr 2012
 by Tom Igoe
 
 */

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

//char tmpStr[3] = "";

// Enter a MAC address for your controller below.
// Newer Ethernet shields have a MAC address printed on a sticker on the shield
byte mac[] = {  
  0x00, 0xAA, 0xBB, 0xCC, 0xDE, 0x02 };
//int cekbohong;

// Initialize the Ethernet client library
// with the IP address and port of the server 
// that you want to connect to (port 80 is default for HTTP):
EthernetClient client;
char server[] = "192.168.0.14";

void setup() {
 // Open serial communications and wait for port to open:
  Serial.begin(9600);
  // this check is only needed on the Leonardo:
   while (!Serial) {
    ; // wait for serial port to connect. Needed for Leonardo only
  }

  // start the Ethernet connection:
  if (Ethernet.begin(mac) == 0) {
    Serial.println("Failed to configure Ethernet using DHCP");
    // no point in carrying on, so do nothing forevermore:
    for(;;)
      ;
  }
  // print your local IP address:
  Serial.print("My IP address: ");
  for (byte thisByte = 0; thisByte < 4; thisByte++) {
    // print the value of each byte of the IP address:
    Serial.print(Ethernet.localIP()[thisByte], DEC);
    Serial.print("."); 
  }
  Serial.println();Serial.println("connecting...");
  
  pinMode(7, OUTPUT);
  
  String data;
  data+="";
  data+="data=1234";
  data+="&submit=Submit"; // Submitting data
  
  if (client.connect("192.168.0.14",80)) 
  {
    Serial.println("connected");
    client.println("POST /CilsyProject/tstarduino2.php HTTP/1.1");
    client.println("Host: 192.168.0.14");
    client.println("Content-Type: application/x-www-form-urlencoded");
    client.println("Connection: close");
    client.print("Content-Length: ");
    client.println(data.length());
    client.println();
    client.print(data);
    client.println();
    
    //Prints your post request out for debugging
    Serial.println("POST /CilsyProject/tstarduino2.php HTTP/1.1");
    Serial.println("Host: 192.168.0.14");
    Serial.println("Content-Type: application/x-www-form-urlencoded");
    Serial.println("Connection: close");
    Serial.print("Content-Length: ");
    Serial.println(data.length());
    Serial.println();
    Serial.print(data);
    Serial.println();
  }
  delay(2000);
  Serial.println("Response: ");
}

void loop()
{  
  while (client.connected() || client.available()) 
  {
    char c = client.read();
    Serial.print(c);
  }         
}

And here is my tstarduino2.php :

<?php

header("Cache-Control: no-cache, must-revalidate"); // HTTP/1.1
header("Expires: Sat, 26 Jul 1997 05:00:00 GMT"); // Date in the past
header("Content-type: text/html");

$data = $_POST["data"];

switch ($data) 
{
	case '1234':
		echo('CorrectAdmin = 1'); 
		break;
	default:
		echo('CorrectAdmin = 0');
		break;
}

?>

The question is, how do i select "CorrectAdmin = 1" from that whole responses in my arduino?

any help would be appreciated :slight_smile:

Can you see a relationship between this code:

header("Cache-Control: no-cache, must-revalidate"); // HTTP/1.1
header("Expires: Sat, 26 Jul 1997 05:00:00 GMT"); // Date in the past
header("Content-type: text/html");

and this output:

HTTP/1.1 200 OK
Date: Fri, 06 Mar 2015 12:30:17 GMT
Server: Apache/2.4.7 (Ubuntu)
X-Powered-By: PHP/5.5.9-1ubuntu4.6
Cache-Control: no-cache, must-revalidate
Expires: Sat, 26 Jul 1997 05:00:00 GMT
Content-Length: 16
Connection: close
Content-Type: text/html

Can you imagine a way to NOT get (some of) that output?

thanks for your quick reply :smiley:

i've deleted that three lines, but i still get this output :

HTTP/1.1 200 OK
Date: Fri, 06 Mar 2015 13:14:31 GMT
Server: Apache/2.4.7 (Ubuntu)
X-Powered-By: PHP/5.5.9-1ubuntu4.6
Content-Length: 16
Connection: close
Content-Type: text/html

CorrectAdmin = 1

But yes, some lines now is not showing after i deleted those three lines.

Since i know that char c = client.read(); function, read only one character one by one, is that possible if i check each of the character? for example if i want when CorrectAdmin = 1, then i will set SomeVariables = true :

(notes : below is not a code)
if c = 'C' then if c='o' then if c = 'r' then if c = 'r' then if c = 'e' then if c = 'c' then if c = 't' then if c = 'A' then if c = 'd' then if c = 'm' then if c = 'i' then if c = 'n' then if c = ' ' then if c = '=' then if c = ' ' then if c = '1' then set SomeVariables = true.

If that is possible, what function should i use?

thanks before :slight_smile:

If that is possible, what function should i use?

The first step is to collect the entire response into an array.
The second step is to parse the array.

There are plenty of examples around of how to do each one.

i've tried this :

arduino sketch

/*
  DHCP-based IP printer
 
 This sketch uses the DHCP extensions to the Ethernet library
 to get an IP address via DHCP and print the address obtained.
 using an Arduino Wiznet Ethernet shield. 
 
 Circuit:
 * Ethernet shield attached to pins 10, 11, 12, 13
 
 created 12 April 2011
 modified 9 Apr 2012
 by Tom Igoe
 
 */

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


// Enter a MAC address for your controller below.
// Newer Ethernet shields have a MAC address printed on a sticker on the shield
byte mac[] = {  
  0x00, 0xAA, 0xBB, 0xCC, 0xDE, 0x02 };

int a;
int b;
int d;
int x = 0;
char dataStr[3];
char c;

// Initialize the Ethernet client library
// with the IP address and port of the server 
// that you want to connect to (port 80 is default for HTTP):
EthernetClient client;
char server[] = "192.168.0.14";

void setup() {
 // Open serial communications and wait for port to open:
  Serial.begin(9600);
  // this check is only needed on the Leonardo:
   while (!Serial) {
    ; // wait for serial port to connect. Needed for Leonardo only
  }

  // start the Ethernet connection:
  if (Ethernet.begin(mac) == 0) {
    Serial.println("Failed to configure Ethernet using DHCP");
    // no point in carrying on, so do nothing forevermore:
    for(;;)
      ;
  }
  // print your local IP address:
  Serial.print("My IP address: ");
  for (byte thisByte = 0; thisByte < 4; thisByte++) {
    // print the value of each byte of the IP address:
    Serial.print(Ethernet.localIP()[thisByte], DEC);
    Serial.print("."); 
  }
  Serial.println();Serial.println("connecting...");
  
  //pinMode(7, OUTPUT);
  
  String data;
  data+="";
  data+="data=4321";
  data+="&submit=Submit"; // Submitting data
  
  if (client.connect("192.168.0.14",80)) 
  {
    Serial.println("connected");
    client.println("POST /CilsyProject/tstarduino2.php HTTP/1.1");
    client.println("Host: 192.168.0.14");
    client.println("Content-Type: application/x-www-form-urlencoded");
    client.println("Connection: close");
    client.print("Content-Length: ");
    client.println(data.length());
    client.println();
    client.print(data);
    client.println();
    
    //Prints your post request out for debugging
    //Serial.println("POST /CilsyProject/tstarduino2.php HTTP/1.1");
    //Serial.println("Host: 192.168.0.14");
    //Serial.println("Content-Type: application/x-www-form-urlencoded");
    //Serial.println("Connection: close");
    //Serial.print("Content-Length: ");
    //Serial.println(data.length());
    //Serial.println();
    //Serial.print(data);
    //Serial.println();
  }
  delay(2000);
  Serial.println("Response: ");
}

void loop()
{  
  while (client.connected() || client.available()) 
  {
    c = client.read();
    if ((c = 'a') || (c='b') || (c='d')){
      dataStr[x] = c;
      x++;
      c = client.read();
      if (c='='){
        dataStr[x] = c;
        x++;
        c = client.read();
        printdata();
      } else {
        cleardata();
      }
    } 
  }         
}

void cleardata() {
  x=0;
}

void printdata() {
  for (x=0;x<3;x++){
    Serial.print(dataStr[x]);
  }
}

php code:

<?php
$data = $_POST["data"];

switch ($data) 
{
	case '1234':
		echo('a=1'); 
		break;
	case '123':
		echo('a=0'); 
		break;
	case '12':
		echo('b=1'); 
		break;
	case '1':
		echo('b=0'); 
		break;
	case '4321':
		echo('d=1'); 
		break;
	case '432':
		echo('d=0'); 
		break;
	default:
		echo('CorrectAdmin = 0');
		break;
}

?>

but when i print the dataStr[x] i always get output like this :

a= a= a=

Even when i change the submit data from 1234 to 4321,432 or 123.

would you please to give me some hints? thanks :slight_smile:

A couple things. First, you are using an assignment, not a comparison. A single equal sign (=) is an assignment, and a double (==) is a comparison. Change those.

Second, you are not concatenating the number to the dataStr array.

      if (c == '='){
        dataStr[x] = c;
        x++;
        c = client.read();
// add this
        dataStr[x] = c;
        printdata();

thanks! i forget about that line :smiley:

i've changed the code :

void loop()
{  
  while (client.connected() || client.available()) 
  {
    c = client.read();
    Serial.print(c);
    if ((c == 'a') || (c =='b') || (c == 'd')){
      dataStr[x] = c;
      x++;
      c = client.read();
      if (c == '='){
        dataStr[x] = c;
        x++;
        c = client.read();
        dataStr[x] = c;
        printdata();
      } else {
        cleardata();
      }
    } 
  }         
}

void cleardata() {
  x=0;
  for (x=0;x<3;x++){
    dataStr[x] = '\0';
  }
}

void printdata() {
  for (x=0;x<3;x++){
    Serial.print(dataStr[x]);
  }
}

But now nothing shows on my Serial Monitor. I've changed the data value to 4321, so the response should be d=1. But nothing shows. It's like the if ((c == 'a') || (c =='b') || (c == 'd')) is not working.

Or my method to clear the Array is wrong? If it is, it's like the array is not letting another input anymore after the clearance. I mean this code :

  x=0;
  for (x=0;x<3;x++){
    dataStr[x] = '\0';
  }

Thanks before :slight_smile:

You can't use a == for string comparison as in your switch. Use strcmp instead.

You can to compare single char with: == 'a'. strcmp is for char arrays: "some string".

but i use char, not string. when i changed my code to this :

void loop()
{  
  while (client.connected() || client.available()) 
  {
    c = client.read();
//    Serial.print(c);
    if (((strcmp(c,"a") == 0) || (strcmp(c,"b") == 0) || (strcmp(c,"d") == 0)){
      dataStr[x] = c;
      x++;
      c = client.read();
      if (((strcmp(c,"=") == 0)){
        dataStr[x] = c;
        x++;
        c = client.read();
        dataStr[x] = c;
        printdata();
      } else {
        cleardata();
      }
    } 
  }
  client.stop();  
}

It can't be verified. I got invalid conversion from 'char' to const char*'

I use char for both c and dataStr. If i change both of them to String, i got ambigous overload for 'operator=' in 'c = Ethernet.client blablabla". I think the ethernet shield reading method should use char data type.

My reference of using strcmp is from this : Comparing 2 strings - Syntax & Programs - Arduino Forum

:slight_smile:

mistergreen:
You can to compare single char with: == 'a'. strcmp is for char arrays: "some string".

oh i'm sorry i didn't notice your reply.

so, would you please give some hints where is my mistakes in my program? i've used if c == 'a' but it looks doesn't work. :slight_smile:

You're making this harder than it needs to be. I would use a unique character for your start and end, like the pipe character "|". Have php echo something like |CorrectAdmin = 1|

//psuedo

look for pipe
if(pipefound)
{
while(!secondpipefound)
{
collect character
append character to char array
}

}

Personally I think it's easier to echo a bunch of variables |6|ON|54|23.4|OFF| this way, and just remember their order in the line. So in this example, I have it hardcoded to get ON or OFF for the second variable. I also like to use unique start and end characters for the entire line to confirm I've gotten them all: ^|6|ON|54|23.4|OFF|^

    c = client.read();

You are reading ONE character. You are NOT reading the entire client response. Do not even try to use the data until you have done that.

stoutfiles:
You're making this harder than it needs to be. I would use a unique character for your start and end, like the pipe character "|". Have php echo something like |CorrectAdmin = 1|

//psuedo

look for pipe
if(pipefound)
{
while(!secondpipefound)
{
collect character
append character to char array
}

}

Personally I think it's easier to echo a bunch of variables |6|ON|54|23.4|OFF| this way, and just remember their order in the line. So in this example, I have it hardcoded to get ON or OFF for the second variable. I also like to use unique start and end characters for the entire line to confirm I've gotten them all: ^|6|ON|54|23.4|OFF|^

oh thank you very much! this really works like a charm!

Since my HTTP Response is not showing any character < and >. So i use it as the unique identifier, but | should be work too.

Here is my Arduino Sketch :

/*
  DHCP-based IP printer
 
 This sketch uses the DHCP extensions to the Ethernet library
 to get an IP address via DHCP and print the address obtained.
 using an Arduino Wiznet Ethernet shield. 
 
 Circuit:
 * Ethernet shield attached to pins 10, 11, 12, 13
 
 created 12 April 2011
 modified 9 Apr 2012
 by Tom Igoe
 
 */

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


// Enter a MAC address for your controller below.
// Newer Ethernet shields have a MAC address printed on a sticker on the shield
byte mac[] = {  
  0x00, 0xAA, 0xBB, 0xCC, 0xDE, 0x02 };

int x = 0; //variable for looping
char dataStr[12]; //create array to store the response. for example : SomeValue1=0 
char c;

// Initialize the Ethernet client library
// with the IP address and port of the server 
// that you want to connect to (port 80 is default for HTTP):
EthernetClient client;
char server[] = "192.168.0.14";

void setup() {
 // Open serial communications and wait for port to open:
  Serial.begin(9600);
  // this check is only needed on the Leonardo:
   while (!Serial) {
    ; // wait for serial port to connect. Needed for Leonardo only
  }

  // start the Ethernet connection:
  if (Ethernet.begin(mac) == 0) {
    Serial.println("Failed to configure Ethernet using DHCP");
    // no point in carrying on, so do nothing forevermore:
    for(;;)
      ;
  }
  // print your local IP address:
  Serial.print("My IP address: ");
  for (byte thisByte = 0; thisByte < 4; thisByte++) {
    // print the value of each byte of the IP address:
    Serial.print(Ethernet.localIP()[thisByte], DEC);
    Serial.print("."); 
  }
  Serial.println();Serial.println("connecting...");
  
  //pinMode(7, OUTPUT);
  
  String data;
  data+="";
  data+="data=123";
  data+="&submit=Submit"; // Submitting data
  
  if (client.connect("192.168.0.14",80)) 
  {
    Serial.println("connected");
    client.println("POST /CilsyProject/tstarduino2.php HTTP/1.1");
    client.println("Host: 192.168.0.14");
    client.println("Content-Type: application/x-www-form-urlencoded");
    client.println("Connection: close");
    client.print("Content-Length: ");
    client.println(data.length());
    client.println();
    client.print(data);
    client.println();
    
    //Prints your post request out for debugging
    //Serial.println("POST /CilsyProject/tstarduino2.php HTTP/1.1");
    //Serial.println("Host: 192.168.0.14");
    //Serial.println("Content-Type: application/x-www-form-urlencoded");
    //Serial.println("Connection: close");
    //Serial.print("Content-Length: ");
    //Serial.println(data.length());
    //Serial.println();
    //Serial.print(data);
    //Serial.println();
  }
  delay(2000);
  Serial.println("Response: ");
}

void loop()
{  
  while (client.connected() || client.available()) 
  {
    c = client.read(); //read first character
    while (c != '<'){ //while < character is not coming yet, keep reading character
      c = client.read();
    }
    c = client.read(); //read the '<' character, but not storing in array
    while (c != '>'){ //while > character is not coming yet,
      dataStr[x] = c; //store character in array
      c = client.read(); //read next character
      x++; //incrementing index array
    }
    printdata(); //print the character that has been captured by array at Serial Monitor
  } 
  client.stop();  //stop connection
}

void printdata() {
  for (x=0;x<12;x++){
    Serial.print(dataStr[x]);
  }
}

And here is my PHP Code :

<?php
$data = $_POST["data"];

switch ($data) 
{
	case '1234':
		echo('<SomeValue1=0>'); 
		break;
	case '123':
		echo('<SomeValue1=1>'); 
		break;
	case '12':
		echo('<SomeValue2=0>'); 
		break;
	case '1':
		echo('<SomeValue2=1>'); 
		break;
	case '4321':
		echo('<SomeValue3=0>'); 
		break;
	case '432':
		echo('<SomeValue3=1>'); 
		break;
	default:
		echo('Nothing to do here');
		break;
}

?>

And here is the output when i input 123 :

My IP address: 192.168.0.16.
connecting...
connected
Response: 
SomeValue1=1

Again, thank you very much for you all! :slight_smile:

So now i'll try to test again that dataStr Array based on the variable (SomeValue1 or SomeValue2 or SomeValue3), then i'll get the last digit (the 0 or 1). Finally convert that last digit into string, then store it to the real SomeValue variable in my Arduino.