Advanced strings in HTML

I want to set up a full-blown arduino website with an SD card: not just a barebones "hello world" html document, but hyperlinks to other pages. When an HTTP request comes in:

Internet Stuff Yadadada
GET \pigs.html
internet stuff

I want the arduino to check for the GET, look up the following thing

pigs.html

Open the file on the SD card and send it to the client. I'm thinking of using a for loop, but I need to know: How to append strings, how to interpret them, etc. I know it from Python, but C++ is different. I would love Python's for loop right now, but I need your help. Can you give me some code? Thanks!

Oh, heres my code littered with bugs that I have NO IDEA what they mean…

#include <SPI.h>
#include <Ethernet.h>
byte mac[] = { 
  0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
IPAddress ip(192,168,1,177);
  EthernetServer server(80);
  void setup() {
  Serial.begin(9600);
  Ethernet.begin(mac, ip);
  server.begin();
  Serial.print("server is at ");
  Serial.println(Ethernet.localIP());
  }
  void loop() {
  EthernetClient client = server.available();
  if (client) {
    Serial.println("knock knock!");
    boolean lineIsBlank = true;
    while (client.connected()) {
      if (client.available()) {
        char c = client.read();
        if(c == '\n' && lineIsBlank) {
        char req[] = client.read(); //get a copy of that HTTP request
        if (char[0,2] == 'GET') {
          char dom[] == '';
          char current == req[5]; //Grab the start of the HTTP Doc Request
          int currentVal == 0 //Number processed
          for(current != ' ', currentVal++) {
            dom[currentVal] = current;
          }
                    client.println("HTTP/1.1 200 OK");
                    client.println("Content-Type: text/html");
                    client.println("Connection: close");
                    client.println();
          
          doc = SD.open(dom);
          if(doc) {
            while(doc.available()) {
              client.write(doc.read());
            }
            doc.close()
          }
          else() {
            Serial.println("Dang! That's a 404!");
            oops = SD.open(404.htm);
            if (oops) {
              while(oops.available()) {
                client.write(oops)
              }
            }
          }
        }
        }
      }
    }
  }

that I have NO IDEA what they mean...

But I'm not going to share them, because they are MY bugs. Go make your own.

Well, OK, be that way.

As a start, put each { on a new line, and use Tools + Auto Format BEFORE posting code here again.

        char req[] = client.read(); //get a copy of that HTTP request

client.read returns ONE character. No need to use an array to store one character.

        if (char[0,2] == 'GET') {

The comma operator is not likely to be doing what you think it is. Single quotes are for one character. Which ONE key did you press to get that ONE character in the single quotes?

          char dom[] == '';

An equality test? WTF?

          char current == req[5]; //Grab the start of the HTTP Doc Request

Another one?

You are in so far over your head that a full diving suit won't help. Time for you to sign up for a basic C programming class, and learn the basics while the Arduino is safely locked in a drawer.

waterlubber: I'm thinking of using a for loop, but I need to know:

That's a simplistic approach to solving the problem. I'm glad you're thinking of the direction "what do I need to know?" However, "using a for loop" is a little too deep dive to be useful. You're going to need a number of skills, including basic control structures like for loops.

waterlubber: How to append strings, how to interpret them, etc.

Yes, you need to spend time on how C handles strings. I would do this separate of your HTML work. Learn how to send and receive characters over serial and then append them to strings. Hint: you do not want to use the Arduino "String" object.

Learn how C++ handles strings. For example, == doesn't work on a string.

waterlubber: I would love Python's for loop right now

I'm really not sure what you mean by this. All programming languages have loop structures. That's just a basic component of the language.

waterlubber:
Can you give me some code?

I’m not going to give you the code, but if you look in the playground I think you will find projects very similar to what you describe.

Okay, taking a codecadamy course when I can...here is my error log:

In file included from AdvServer.ino:2:
C:\Program Files (x86)\Arduino\libraries\Ethernet/Ethernet.h:6:23: error: IPAddress.h: No such file or directory
In file included from C:\Program Files (x86)\Arduino\libraries\Ethernet/Ethernet.h:7,
                 from AdvServer.ino:2:
C:\Program Files (x86)\Arduino\libraries\Ethernet/EthernetClient.h:5:20: error: Client.h: No such file or directory
In file included from C:\Program Files (x86)\Arduino\libraries\Ethernet/Ethernet.h:8,
                 from AdvServer.ino:2:
C:\Program Files (x86)\Arduino\libraries\Ethernet/EthernetServer.h:4:20: error: Server.h: No such file or directory
AdvServer.ino:25:25: error: empty character constant
AdvServer.ino:45:28: error: invalid suffix "htm" on floating constant
In file included from AdvServer.ino:1:
C:\Program Files (x86)\Arduino\libraries\SPI/SPI.h: In static member function 'static byte SPIClass::transfer(byte)':
C:\Program Files (x86)\Arduino\libraries\SPI/SPI.h:56: error: 'SPDR' was not declared in this scope
C:\Program Files (x86)\Arduino\libraries\SPI/SPI.h:57: error: 'SPSR' was not declared in this scope
C:\Program Files (x86)\Arduino\libraries\SPI/SPI.h:57: error: 'SPIF' was not declared in this scope
C:\Program Files (x86)\Arduino\libraries\SPI/SPI.h: In static member function 'static void SPIClass::attachInterrupt()':
C:\Program Files (x86)\Arduino\libraries\SPI/SPI.h:63: error: 'SPCR' was not declared in this scope
C:\Program Files (x86)\Arduino\libraries\SPI/SPI.h:63: error: 'SPIE' was not declared in this scope
C:\Program Files (x86)\Arduino\libraries\SPI/SPI.h: In static member function 'static void SPIClass::detachInterrupt()':
C:\Program Files (x86)\Arduino\libraries\SPI/SPI.h:67: error: 'SPCR' was not declared in this scope
C:\Program Files (x86)\Arduino\libraries\SPI/SPI.h:67: error: 'SPIE' was not declared in this scope
In file included from C:\Program Files (x86)\Arduino\libraries\Ethernet/Ethernet.h:7,
                 from AdvServer.ino:2:
C:\Program Files (x86)\Arduino\libraries\Ethernet/EthernetClient.h: At global scope:
C:\Program Files (x86)\Arduino\libraries\Ethernet/EthernetClient.h:8: error: expected class-name before '{' token
C:\Program Files (x86)\Arduino\libraries\Ethernet/EthernetClient.h:15: error: 'IPAddress' has not been declared
C:\Program Files (x86)\Arduino\libraries\Ethernet/EthernetClient.h:30: error: type 'Print' is not a base type for type 'EthernetClient'
In file included from C:\Program Files (x86)\Arduino\libraries\Ethernet/Ethernet.h:8,
                 from AdvServer.ino:2:
C:\Program Files (x86)\Arduino\libraries\Ethernet/EthernetServer.h:9: error: expected class-name before '{' token
C:\Program Files (x86)\Arduino\libraries\Ethernet/EthernetServer.h:19: error: type 'Print' is not a base type for type 'EthernetServer'
In file included from C:\Program Files (x86)\Arduino\libraries\Ethernet/Dhcp.h:7,
                 from C:\Program Files (x86)\Arduino\libraries\Ethernet/Ethernet.h:9,
                 from AdvServer.ino:2:
C:\Program Files (x86)\Arduino\libraries\Ethernet/EthernetUdp.h:44: error: expected class-name before '{' token
C:\Program Files (x86)\Arduino\libraries\Ethernet/EthernetUdp.h:48: error: 'IPAddress' does not name a type
C:\Program Files (x86)\Arduino\libraries\Ethernet/EthernetUdp.h:62: error: 'IPAddress' has not been declared
C:\Program Files (x86)\Arduino\libraries\Ethernet/EthernetUdp.h:74: error: type 'Print' is not a base type for type 'EthernetUDP'
C:\Program Files (x86)\Arduino\libraries\Ethernet/EthernetUdp.h:94: error: 'IPAddress' does not name a type
In file included from C:\Program Files (x86)\Arduino\libraries\Ethernet/Ethernet.h:9,
                 from AdvServer.ino:2:
C:\Program Files (x86)\Arduino\libraries\Ethernet/Dhcp.h:168: error: 'IPAddress' does not name a type
C:\Program Files (x86)\Arduino\libraries\Ethernet/Dhcp.h:169: error: 'IPAddress' does not name a type
C:\Program Files (x86)\Arduino\libraries\Ethernet/Dhcp.h:170: error: 'IPAddress' does not name a type
C:\Program Files (x86)\Arduino\libraries\Ethernet/Dhcp.h:171: error: 'IPAddress' does not name a type
C:\Program Files (x86)\Arduino\libraries\Ethernet/Dhcp.h:172: error: 'IPAddress' does not name a type
In file included from AdvServer.ino:2:
C:\Program Files (x86)\Arduino\libraries\Ethernet/Ethernet.h:15: error: 'IPAddress' does not name a type
C:\Program Files (x86)\Arduino\libraries\Ethernet/Ethernet.h:24: error: 'IPAddress' has not been declared
C:\Program Files (x86)\Arduino\libraries\Ethernet/Ethernet.h:25: error: 'IPAddress' has not been declared
C:\Program Files (x86)\Arduino\libraries\Ethernet/Ethernet.h:25: error: 'IPAddress' has not been declared
C:\Program Files (x86)\Arduino\libraries\Ethernet/Ethernet.h:26: error: 'IPAddress' has not been declared
C:\Program Files (x86)\Arduino\libraries\Ethernet/Ethernet.h:26: error: 'IPAddress' has not been declared
C:\Program Files (x86)\Arduino\libraries\Ethernet/Ethernet.h:26: error: 'IPAddress' has not been declared
C:\Program Files (x86)\Arduino\libraries\Ethernet/Ethernet.h:27: error: 'IPAddress' has not been declared
C:\Program Files (x86)\Arduino\libraries\Ethernet/Ethernet.h:27: error: 'IPAddress' has not been declared
C:\Program Files (x86)\Arduino\libraries\Ethernet/Ethernet.h:27: error: 'IPAddress' has not been declared
C:\Program Files (x86)\Arduino\libraries\Ethernet/Ethernet.h:27: error: 'IPAddress' has not been declared
C:\Program Files (x86)\Arduino\libraries\Ethernet/Ethernet.h:30: error: 'IPAddress' does not name a type
C:\Program Files (x86)\Arduino\libraries\Ethernet/Ethernet.h:31: error: 'IPAddress' does not name a type
C:\Program Files (x86)\Arduino\libraries\Ethernet/Ethernet.h:32: error: 'IPAddress' does not name a type
C:\Program Files (x86)\Arduino\libraries\Ethernet/Ethernet.h:33: error: 'IPAddress' does not name a type
AdvServer:5: error: 'IPAddress' does not name a type
AdvServer:7: error: expected ',' or ';' before 'void'
AdvServer.ino: In function 'void loop()':
AdvServer:23: error: initializer fails to determine size of 'req'
AdvServer:24: error: expected primary-expression before 'char'
AdvServer:24: error: expected `)' before 'char'
AdvServer:25: error: expected initializer before '==' token
AdvServer:26: error: expected initializer before '==' token
AdvServer:27: error: expected initializer before '==' token
AdvServer:31: error: 'class EthernetClient' has no member named 'println'
AdvServer:32: error: 'class EthernetClient' has no member named 'println'
AdvServer:33: error: 'class EthernetClient' has no member named 'println'
AdvServer:34: error: 'class EthernetClient' has no member named 'println'
AdvServer:36: error: 'doc' was not declared in this scope
AdvServer:36: error: 'SD' was not declared in this scope
AdvServer:36: error: 'dom' was not declared in this scope
AdvServer:42: error: expected `;' before '}' token
AdvServer:43: error: expected primary-expression before ')' token
AdvServer:43: error: expected `;' before '{' token
AdvServer:56: error: expected `}' at end of input
AdvServer:56: error: expected `}' at end of input
AdvServer:56: error: expected `}' at end of input
AdvServer:56: error: expected `}' at end of input
AdvServer:56: error: expected `}' at end of input
AdvServer:56: error: expected `}' at end of input

The IPAddress line in my code throws an error for some reason...

C:\Program Files (x86)\Arduino\libraries\Ethernet/Ethernet.h:6:23: error: IPAddress.h: No such file or directory
In file included from C:\Program Files (x86)\Arduino\libraries\Ethernet/Ethernet.h:7,
                 from AdvServer.ino:2:

Could someone explain this error:

'IPAddress' Does not name a type

It appears to be from this part of my code:

#include <SPI.h>
#include <Ethernet.h>
byte mac[] = {0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED};
IPAddress ip(192,168,1,120);
EthernetServer server(80);

Bah! Ignore all the error logs you see…I simplafied this to no end. It’s simple now, but there is ONE thing I need to know:
How do I accept any size for a string? The code goes through the request and tries to find the filename…does it NEED to be a certain size?
If the request is like this:

[GET /index.html HTTP/1.1

How would I find the ‘index.html’ find the corrosponding file on the SD card, then send it to the client? I need to have an open-ended string side so I don’t…gulp…write to random memory bits when reading it. Is there a way to create a self-growing sting? Can someone help me out? My code so far is this:

#include <SPI.h>
#include <Ethernet.h>
#include <SD.h>
byte mac[] = {0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED};
IPAddress ip(192,168,1,120);
EthernetServer server(80);
char current = '';
char FileName[7];
char doc[];
int x;

void setup()
{
  Serial.begin(9600);
  Ethernet.begin(mac, ip);
  server.begin(); //Boot!
  SD.begin(); //Start reading from that SD Car there
}

void loop() {
  EthernetClient client = server.available();
  if(client) {
    Serial.println("Request Recieved!");
    while (client.connected()) {
      if (client.available()) {
        int PacketSize = client.parsePacket();
        client.read(Packet,30);
        delay(100); //Wait a bit for it to get that request! It's big!
        Serial.print(Packet[0,29]);
        if(Packet[0] == 'G' && Packet[1] == 'E' && Packet[2] == 'T') {
          for(x=5; current != ' '; x++)
          {
          FileName[x-5] = Packet[x];
          current = Packet[x+1];
          }
        }
        Serial.print("File name is: ");
        Serial.println(FileName);
        doc = SD.open(FileName);
      }
    }
  }
}

Now my errors are mostly gone (I was compiling for the At Tiny, thats why it was so weird…

sketch_feb25a.ino:7:16: error: empty character constant
sketch_feb25a:9: error: storage size of 'doc' isn't known
sketch_feb25a.ino: In function 'void loop()':
sketch_feb25a:26: error: 'class EthernetClient' has no member named 'parsePacket'
sketch_feb25a:27: error: 'Packet' was not declared in this scope

Anybody have a secret command that can help me?

Can't I declare an unset string size?

No, you can't. How is the compiler supposed to know how much memory to reserve?

        int PacketSize = client.parsePacket();

You can't just pick methods that exist in one class and use them with another class. parsePacket() is a member of the EthernetUDP class, not the Ethernet class.

        client.read(Packet,30);

You haven't defined a variable called Packet. Where did the 30 come from?

        Serial.print(Packet[0,29]);

You are obviously not familiar with what the comma operator does. This is NOT how to print the first 30 characters of an array.

        doc = SD.open(FileName);

The SD.open() method returns a file handle, not an array of chars. NOTHING returns an array of anything. It's just not possible.

There appears to be something wrong with your installation of the IDE (or you are trying to use a post 1.0 library with a pre-1.0 version of the IDE). Which version of the IDE are you using?

I just realized I set the board to ATTiny, I fixed it, and I can debug it all I guess if I can

char Packet[] = client.read()

But I've heard that wouldn't work. How do I send the file? Could I just do it directly? Please help!

How do I send the file? Could I just do it directly? Please help!

I replied in you other thread. Which is why we ask people to NOT start new threads about the same topic.

Thank god, I fished out most of the errors. Now, all I need to do is resolved this 1 weird bug (wow, that sounded like an ad) Pastebin: (tired of reposting to update code) http://pastebin.com/pDE7vRti

Here's the error:

sketch_feb25a.ino:7:16: error: empty character constant
sketch_feb25a.ino: In function 'void loop()':
sketch_feb25a:25: error: initializer fails to determine size of 'Packet'
sketch_feb25a:37: error: 'doc' was not declared in this scope

Pastebin: (tired of reposting to update code)

Well, I don't do rubbish bin, so I'm done.

But, think about this. A file name on the Arduino only means something if you have an SD card reader. And, on the SD card, files are limited to 8 characters for the name and 3 for the extension. So, 13 bytes total, including the . and the terminating NULL.

Just make the array size 13 and quit fighting that battle. You WILL lose.

Okay, then, don't understand why you hate paste bin, but why does it say

sketch_feb25a:37: error: 'doc' was not declared in this scope

Okay, then, don't understand why you hate paste bin,

Possibly because of this:

Your request has been blocked by ******** Information Security

******* blocks Web sites which contain inappropriate content, those that contain malicious code, and those that provide services that may be unsafe to the Boeing network and or its resources.

URL: http://pastebin.com/pDE7vRti Categories: Personal Network Storage Proxy: wp-blv-20

Or possibly for other reasons.

but why does it say

If you haven't added a size to the declaration, then the statement was rejected, and doc is NOT defined. In any scope.

Gotta hate those web filters! Anyway, I fixed all the buggles, (I think) and the compiler almost shut up… except for one thing…

Here’s the code:

#include <SPI.h>
#include <Ethernet.h>
#include <SD.h>
byte mac[] = {0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED};
IPAddress ip(192,168,1,120);
EthernetServer server(80);
char current;
char FileName[8];
char Packet[22];
int x;

void setup()
{
  Serial.begin(9600);
  Ethernet.begin(mac, ip);
  server.begin(); //Boot!
  SD.begin(); //Start reading from that SD Car there
}

void loop() {
  EthernetClient client = server.available();
  if(client) {
    Serial.println("Request Recieved!");
    while (client.connected()) {
      if (client.available()) {
        char c;
        for(int x = 0; c != '/n' && x<22; x++) {
          c = client.read();
          Packet[x] = c;
        }
        if(Packet[0] == 'G' && Packet[1] == 'E' && Packet[2] == 'T') {
          for(x=5; current != ' '; x++)
          {
          FileName[x-5] = Packet[x];
          current = Packet[x+1];
          }
        }
        Serial.print("File name is: ");
        Serial.println(FileName);
        myFile = SD.open(FileName);
        if(doc) {
          client.println("HTTP/1.1 200 OK");
          client.println("Content-Type: text/html");
          client.println("Connection: close");
          client.print(doc.read());
      }
    }
  }
}
}

It’s this part that the compiler yaps about:

        Serial.print("File name is: ");
        Serial.println(FileName);
        myFile = SD.open(FileName);
        if(doc) {

Here’s what it says:

AdvServer.ino: In function 'void loop()':
AdvServer:40: error: 'myFile' was not declared in this scope
AdvServer:41: error: 'doc' was not declared in this scope

In my code, I get this error message when I try to use an SD.open() command:

AdvServer.ino: In function 'void loop()':
AdvServer:40: error: 'myFile' was not declared in this scope
AdvServer:41: error: 'doc' was not declared in this scope

This is my code

#include <SPI.h>     //The SPI Bus
#include <Ethernet.h>//Ethernet Chip stuff
#include <SD.h>      //SD Card
byte mac[] = {0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED}; //Unique identifier that...I can pick!
IPAddress ip(192,168,1,120); //IP Adress that...I picked!
EthernetServer server(80); //It's important.
char current; //Current Parsing Char
char FileName[8]; //You'll see
int x; //A number

void setup()
{
  Serial.begin(9600);
  Ethernet.begin(mac, ip);
  server.begin(); //Boot!
  SD.begin(); //Start reading from that SD Car there
}

void loop() {
  EthernetClient client = server.available();
  if(client) { //Anyone Home?
    Serial.println("Request Recieved!");
    while (client.connected()) {
      char Packet[client.available()];
      if (client.available()) {
        char c;
        for(int x = 0; c != '/n' && x<22; x++) {
          c = client.read();
          Packet[x] = c;
        }
        if(Packet[0] == 'G' && Packet[1] == 'E' && Packet[2] == 'T') {
          for(x=5; current != ' '; x++)
          {
          FileName[x-5] = Packet[x];
          current = Packet[x+1];
          }
        }
        Serial.print("File name is: ");
        Serial.println(FileName);
        myFile=SD.open(FileName);
        if(myFile) {
          client.println("HTTP/1.1 200 OK");
          client.println("Content-Type: text/html");
          client.println("Connection: close");
          client.print(myFile.read());
      }
    }
  }
}
}

Anybody know whats going on? The compiler is getting in the way!

So, where IS myFile declared? I don't see it. Or doc, for that matter. It looks like you are treating doc as a file handle, and using it where you mean to use myFile.

Oops. Typo. I fixed it, same result. "myFile was not declared in pigs, please go get a life…well, not exactly, but that’s my interpretation.

#include <SPI.h>     //The SPI Bus
#include <Ethernet.h>//Ethernet Chip stuff
#include <SD.h>//SD Card
byte mac[] = {0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED}; //Unique identifier that...I can pick!
IPAddress ip(192,168,1,120); //IP Adress that...I picked!
EthernetServer server(80); //It's important.
char current; //Current Parsing Char
char FileName[8]; //You'll see
char Packet[22]; //The Packet's warm place to live
int x; //A number

void setup()
{
  Serial.begin(9600);
  Ethernet.begin(mac, ip);
  server.begin(); //Boot!
  SD.begin(); //Start reading from that SD Car there
}

void loop() {
  EthernetClient client = server.available();
  if(client) { //Anyone Home?
    Serial.println("Request Recieved!");
    while (client.connected()) {
      if (client.available()) {
        char c;
        for(int x = 0; c != '/n' && x<22; x++) {
          c = client.read();
          Packet[x] = c;
        }
        if(Packet[0] == 'G' && Packet[1] == 'E' && Packet[2] == 'T') {
          for(x=5; current != ' '; x++)
          {
          FileName[x-5] = Packet[x];
          current = Packet[x+1];
          }
        }
        Serial.print("File name is: ");
        Serial.println(FileName);
        myFile = SD.open(FileName);
        if(myFile) {
          client.println("HTTP/1.1 200 OK");
          client.println("Content-Type: text/html");
          client.println("Connection: close");
          client.print(myFile.read());
      }
    }
  }
}
}

Same error.

AdvServer.ino: In function 'void loop()':
AdvServer:40: error: 'myFile' was not declared in this scope

The compiler is getting in the way!

Of you being stupid? You have not declared those variables!