I'm writing a sketch to control Roomba over internet. However I'm having most problems with processing webpage input in the sketch
Below is the test sketch I use, it just displays page with simple links that pass variables via GET method. It just outputs to serial some text depending on which link is pressed (i.e. Go Forward!).
However for some reason it doesn't work right. For example when I click forward first time, it echoes Go Forward!, but if I now click Backward it echoes "Go Forward! Go Backward!". I have no clue why it does it. It seems to remember last value...
#include <SPI.h>
#include <Ethernet.h>
byte mac[] = {
0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
IPAddress ip(192,168,1, 113);
EthernetServer server(80);
String HTTP_req; // stores the HTTP request
boolean LED_status = 0; // state of LED, off by default
byte LEDPin = 13;
void setup()
{
Ethernet.begin(mac, ip); // initialize Ethernet device
server.begin(); // start to listen for clients
Serial.begin(115200); // for diagnostics
Serial.print("server is at ");
Serial.println(Ethernet.localIP());
}
void loop()
{
EthernetClient client = server.available(); // try to get client
if (client) { // got client?
boolean currentLineIsBlank = true;
while (client.connected()) {
if (client.available()) { // client data available to read
char c = client.read(); // read 1 byte (character) from client
HTTP_req += c; // save the HTTP request 1 char at a time
// last line of client request is blank and ends with \n
// respond to client only after last line received
if (c == '\n' && currentLineIsBlank) {
// send a standard http response header
sendHeader(client);
// send web page
showBody(client);
processDir(client);
Serial.print(HTTP_req);
HTTP_req = ""; // finished with request, empty string
break;
}
// every line of text received from the client ends with \r\n
if (c == '\n') {
// last character on line of received text
// starting new line with next character read
currentLineIsBlank = true;
}
else if (c != '\r') {
// a text character was received from client
currentLineIsBlank = false;
}
} // end if (client.available())
} // end while (client.connected())
delay(1); // give the web browser time to receive the data
client.stop(); // close the connection
} // end if (client)
}
void sendHeader(EthernetClient client){
client.println("HTTP/1.1 200 OK");
client.println("Content-Type: text/html");
client.println("Connection: close");
client.println();
}
void showBody (EthernetClient client){
client.println ("<html><head><title></title></head>");
client.println ("<body><h1>Test Page</h1><p><a href='?myDir=FW'>Forward </a>| <a href='?myDir=BW'>Back </a>| <a href='?myDir=ST'>Stop</a></p></p></body></html>");
}
void processDir (EthernetClient client){
if (HTTP_req.indexOf("myDir=FW") > -1) Serial.println ("Go Forward!");
if (HTTP_req.indexOf("myDir=BW") > -1) Serial.println ("Go Back!");
if (HTTP_req.indexOf("myDir=ST") > -1) Serial.println ("All Stop!");
}
And by all means if you can suggest a better way to process input please do. Using Strings (memory leaks) and "indexOf" kind of bothers me, but I'm not sure if there's a better way
bratan:
And by all means if you can suggest a better way to process input please do. Using Strings (memory leaks) and "indexOf" kind of bothers me, but I'm not sure if there's a better way
Use strings (null terminated char array) and strstr(). You can reduce the size of the string buffer by processing line by line, rather than all at once.
bratan:
Using Strings (memory leaks) and "indexOf" kind of bothers me, but I'm not sure if there's a better way
There is the standard C string, (array of chars), which in my opinion are easier to use (since I never used the String class). With arrays of chars you use the function strcmp (or maybe better in your case: strncmp) to compare 2 strings. Try it, it will most likely solve your problem
bratan:
Using Strings (memory leaks) and "indexOf" kind of bothers me, but I'm not sure if there's a better way
There is the standard C string, (array of chars), which in my opinion are easier to use (since I never used the String class). With arrays of chars you use the function strcmp (or maybe better in your case: strncmp) to compare 2 strings. Try it, it will most likely solve your problem
Thank you!
You mean define string as: char myString[X] ? How would I know that size of array should be?
bratan:
Thank you!
You mean define string as: char myString[X] ? How would I know that size of array should be?
If you go line by line, it would only need to be big enough to accommodate the line that has the data you're looking for. You just have to be careful to make sure you don't put more data in it than it can handle.
Serial.print(HTTP_req);
HTTP_req = ""; // finished with request, empty string
Why not print the GET request first? That way, you'd know what you are parsing.
Why not share that output with us? You are the only one that can see it, so there is only one of us that can actually help you.
Good point. I switched it around. Here's output. I basically first loaded page, then pressed Forward, then Back twice.
server is at 192.168.1.113
GET / HTTP/1.1
Host: 192.168.1.113
User-Agent: Mozilla/5.0 (Windows NT 6.2; WOW64; rv:21.0) Gecko/20100101 Firefox/21.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Connection: keep-alive
GET /?myDir=FW HTTP/1.1
Host: 192.168.1.113
User-Agent: Mozilla/5.0 (Windows NT 6.2; WOW64; rv:21.0) Gecko/20100101 Firefox/21.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Referer: http://192.168.1.113/
Connection: keep-alive
Go Forward!
GET /?myDir=BW HTTP/1.1
Host: 192.168.1.113
User-Agent: Mozilla/5.0 (Windows NT 6.2; WOW64; rv:21.0) Gecko/20100101 Firefox/21.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Referer: http://192.168.1.113/?myDir=FW
Connection: keep-alive
Go Forward!
Go Back!
GET /?myDir=BW HTTP/1.1
Host: 192.168.1.113
User-Agent: Mozilla/5.0 (Windows NT 6.2; WOW64; rv:21.0) Gecko/20100101 Firefox/21.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Referer: http://192.168.1.113/?myDir=BW
Connection: keep-alive
Go Back!
//zoomkat 4-1-12
//simple button GET for servo and pin 5
//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 ' instead of "
//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>
#include <Servo.h>
Servo myservo; // create servo object to control a servo
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();
myservo.write(90); //set initial servo position if desired
myservo.attach(7); //the pin for the servo control
//enable serial data print
Serial.begin(9600);
Serial.println("server servo/pin 5 test 1.0"); // 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
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=\"/?on\">ON</a>");
client.println("<a href=\"/?off\">OFF</a>");
client.println("</BODY>");
client.println("</HTML>");
delay(1);
//stopping client
client.stop();
///////////////////// control arduino pin
if(readString.indexOf("on") >0)//checks for on
{
myservo.write(40);
digitalWrite(5, HIGH); // set pin 5 high
Serial.println("Led On");
}
if(readString.indexOf("off") >0)//checks for off
{
myservo.write(140);
digitalWrite(5, LOW); // set pin 5 low
Serial.println("Led Off");
}
//clearing string for next read
readString="";
}
}
}
}
}
Neat! Thanks for sharing!
I also got mine working. It drives Roomba across the room Although bumper sensors are not working for some strange reason (I enabled Safe mode which suppose to override any movement if Roomba encounters obstacle). Am attaching the code (very rough, but it works!) in case anyone is interested. It uses Serial1 ports of Arduino Mega, so if you have Uno you'll need to adjust it (use SoftwareSerial instead).