Is it possible to receive a HTTP Post request with my Arduino Uno using a Ethernet shield. I want to make an Android app wich can control me Arduino and I thought the best way t
A POST looks like:
POST /test.php HTTP/1.1
Host: 192.168.0.55
Content-Type: application/x-www-form-urlencoded
Connection: close
User-Agent: Arduino/1.0
Content-Length: 1024
data=5
So you have to ignore first "newline" and read on. Here is my modified Web Server code to read posted data:
/*
Web Server
*/
#include <SPI.h>
#include <Ethernet.h>
// Enter a MAC address and IP address for your controller below.
// The IP address will be dependent on your local network:
byte mac[] = {
0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED
};
IPAddress ip(192, 168, 15, 177);
// Initialize the Ethernet server library
// with the IP address and port you want to use
// (port 80 is default for HTTP):
EthernetServer server(80);
void setup() {
// Open serial communications and wait for port to open:
Serial.begin(9600);
while (!Serial) {
; // wait for serial port to connect. Needed for native USB port only
}
// start the Ethernet connection and the server:
//Ethernet.begin(mac, ip);
Ethernet.begin(mac);
server.begin();
Serial.print("server is at ");
Serial.println(Ethernet.localIP());
}
void writeResponse(EthernetClient client) {
// send a standard http response header
client.println("HTTP/1.1 200 OK");
client.println("Content-Type: text/html");
client.println("Connection: close"); // the connection will be closed after completion of the response
// client.println("Refresh: 5"); // refresh the page automatically every 5 sec
client.println();
client.println("<!DOCTYPE HTML>");
client.println("<html> <body>");
// output the value of each analog input pin
for (int analogChannel = 0; analogChannel < 6; analogChannel++) {
int sensorReading = analogRead(analogChannel);
client.print("analog input ");
client.print(analogChannel);
client.print(" is ");
client.print(sensorReading);
client.println("<br />");
}
client.println("<form action=\"\" method=\"post\">");
client.println("<input type=\"submit\" value=\"On\" name=\"btnOn\">");
client.println("<input type=\"submit\" value=\"Off\" name=\"btnOff\">");
client.println("</form>");
client.println("</body> </html>");
}
void loop() {
// listen for incoming clients
EthernetClient client = server.available();
if (client) {
Serial.print("new client [");
//Serial.print(client.getRemoteIP());
//Serial.println("]");
// an http request ends with a blank line
boolean currentLineIsBlank = true;
String req_str = "";
int data_length = -1;
boolean skip = true;
//int empty_line_count = 0;
while (client.connected())
{
if (client.available()) {
char c = client.read();
//Serial.write(c);
req_str += c;
// if you've gotten to the end of the line (received a newline
// character) and the line is blank, the http request has ended,
// so you can send a reply
if (c == '\n' && currentLineIsBlank && req_str.startsWith("GET")) {
writeResponse(client);
break;
}
if (c == '\n' && currentLineIsBlank && req_str.startsWith("POST") && !skip) {
writeResponse(client);
break;
}
if (c == '\n' && currentLineIsBlank && req_str.startsWith("POST") && skip) {
skip = false;
String temp = req_str.substring(req_str.indexOf("Content-Length:") + 15);
temp.trim();
//Serial.print("Content-Length=");
data_length = temp.toInt();
/*Serial.println(data_length);
writeResponse(client);
break;*/
while(data_length-- > 0)
{
c = client.read();
req_str += c;
}
writeResponse(client);
break;
}
if (c == '\n') {
// you're starting a new line
currentLineIsBlank = true;
} else if (c != '\r') {
// you've gotten a character on the current line
currentLineIsBlank = false;
}
}
}
Serial.println(req_str);
// give the web browser time to receive the data
delay(1);
// close the connection:
client.stop();
Serial.println("client disconnected");
}
}
I wanted to read a POST like you instead of using a GET. I did it like this:
/*
A simple Arduino Ethernet web server.
by John Harrison
*/
#include <SPI.h>
#include <Ethernet.h>
// You can change the MAC and IP addresses to suit your network:
byte mac[] = { 0X52, 0X64, 0X75, 0X69, 0X6E, 0X6F };
IPAddress ip( 192,168,0,97 );
EthernetServer server(80); // Port 80 is HTTP port
char new_state[1024];
void setup()
{
Serial.begin(9600);
// Start the Ethernet server:
Ethernet.begin(mac, ip);
server.begin();
// Set the digital pins ready to write to
for (int pin = 2; pin <= 9; pin++) {
pinMode(pin, OUTPUT);
}
Serial.print("Serving on http://");
Serial.println(Ethernet.localIP());
}
void loop()
{
// listen for incoming clients
EthernetClient client = server.available();
if (client) {
// Serial.println("Client connected");
while (client.connected()) {
int i = 0;
int head = 1;
int body = 0;
while(client.available()) {
char c = client.read();
if (c == '\n') {
if ( i <= 2 ) {
// an http request ends with a blank line
sendPage(client);
if ( head == 1 ) {
body = 1;
head = 0;
}
}
i = -1;
}
if ( body == 1 ) {
new_state[i] = c;
}
i++;
new_state[i] = '\0';
}
i = 0;
}
// Serial.println("Disconnected");
/*
if ( strlen(new_state) > 0 ){
Serial.print ("[");
Serial.print(new_state);
Serial.println ("]");
}
*/
// Post data looks like pinD2=On
if ( strncmp( new_state, "pinD", 4) == 0 ) {
int pin = new_state[4] - 48; // Convert ascii to int
// Serial.println(pin);
if ( strncmp( new_state+5, "=On", 3) == 0 ) {
digitalWrite(pin, 1);
}
else if ( strncmp( new_state+5, "=Off", 4) == 0 ) {
digitalWrite(pin, 0);
}
}
}
}
void sendPage(EthernetClient client)
{
// Serial.println("Sending response");
// send a standard http response header
client.println("HTTP/1.0 200 OK\Content-Type: text/html\n\n<html>\n<head>");
client.println("<link rel='icon' href='data:;base64,iVBORw0KGgo='>");
client.println("<title>POST Pin controller</title>\n</head>\n<body>\n");
client.println("<h2>Buttons turn pins on or off</h2>");
client.println("<form method='post' action='/' name='pins'>");
char line[1024];
int pin;
for ( pin=2; pin<=9; pin++ ) {
sprintf(line, "<input name='pinD%d' type='submit' value='On' />\n", pin);
client.print(line);
sprintf(line, "<input name='pinD%d' type='submit' value='Off' /> %d<br />\n", pin, pin);
client.print(line);
}
client.println("</form>\n</body>\n</html>");
client.stop();
}
There are ways to do it which are simpler and smaller, but I found them quite laggy so have been trying to get it as fast as possible.
I have used this to control 8 LEDs on pins 2-9 on a Mega 2560. I haven't tested it on a Uno yet, but I expect it would work the same.
Not sure about POST, but GET definitely works. Here's an AJAX example that I've been using that works. It just controls an RGB LED.
xmlhttp.open("GET", "http://ipAddressOfArduino?r=" + redVal + "&g=" + greenVal + "&b=" + blueVal + "&e", true);
Then on the Arduino side, I just parse the data.
//ARDUINO 1.0+ ONLY
//ARDUINO 1.0+ ONLY
#include <Ethernet.h>
#include <SPI.h>
boolean reading = false;
String myStr;
int redVal, greenVal, blueVal;
////////////////////////////////////////////////////////////////////////
//CONFIGURE
////////////////////////////////////////////////////////////////////////
//byte ip[] = { 192, 168, 0, 1 }; //Manual setup only
//byte gateway[] = { 192, 168, 0, 1 }; //Manual setup only
//byte subnet[] = { 255, 255, 255, 0 }; //Manual setup only
// if need to change the MAC address (Very Rare)
byte mac[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
EthernetServer server = EthernetServer(80); //port 80
////////////////////////////////////////////////////////////////////////
void setup(){
Serial.begin(9600);
pinMode(3, OUTPUT);
pinMode(5, OUTPUT);
pinMode(6, OUTPUT);
Ethernet.begin(mac);
//Ethernet.begin(mac, ip); //for manual setup
server.begin();
Serial.println(Ethernet.localIP());
}
void loop(){
// listen for incoming clients, and process qequest.
checkForClient();
}
void checkForClient(){
EthernetClient client = server.available();
if (client) {
// an http request ends with a blank line
boolean currentLineIsBlank = true;
boolean sentHeader = false;
myStr = "";
while (client.connected()) {
if (client.available()) {
char c = client.read();
if(reading && c == ' ') reading = false;
if(c == '?') reading = true; //found the ?, begin reading the info
if(reading){
//Serial.print(c);
if (c!='?') {
myStr += c;
}
}
if (c == '\n' && currentLineIsBlank) break;
if (c == '\n') {
currentLineIsBlank = true;
}else if (c != '\r') {
currentLineIsBlank = false;
}
}
}
parseThangs(myStr);
analogWrite(3, redVal);
analogWrite(5, greenVal);
analogWrite(6, blueVal);
delay(100); // give the web browser time to receive the data
client.stop(); // close the connection:
}
}
void parseThangs(String str) {
int startIndex = str.indexOf("r");
int endIndex = str.indexOf("g");
String redStr = str.substring(startIndex + 2, endIndex - 1);
char tempRed[4];
redStr.toCharArray(tempRed, sizeof(tempRed));
redVal = atoi(tempRed);
startIndex = str.indexOf("g");
endIndex = str.indexOf("b");
String greenStr = str.substring(startIndex + 2, endIndex -1);
char tempGreen[4];
greenStr.toCharArray(tempGreen, sizeof(tempGreen));
greenVal = atoi(tempGreen);
startIndex = str.indexOf("b");
endIndex = str.indexOf("e");
String blueStr = str.substring(startIndex + 2, endIndex -1);
char tempBlue[4];
blueStr.toCharArray(tempBlue, sizeof(tempBlue));
blueVal = atoi(tempBlue);
Serial.println(redStr + " " + greenStr + " " + blueStr);
}
Probably a little sloppy, but it works.