The sketch is based around the simpleserver example that handles all the web server grunt work. It works like this: in the loop area of the arduino there is a line "WiServer.server_task();" that would be a function to run all of the server functions, upkeep the wireless board, and respond to page requests on the line. When a page request is found on the line the function
boolean SendPage(char* URL)
is run. At it's heart this function just tells the server what message to return as html as the page is requested. There is no fancy hard drive access to get web pages here though, just a URL passed in and a function "WiServer.print()" to print output. Because the URL is passed in however we can roll over it to do things by accessing the URL variable. This might respond to simple URL page requests:
//something like
if (substr(URL, 1, 5) == "test") //if characters 2 to 6 were "test"
{
WiServer.print("test was entered"); //this is written as page output and displayed by the browser
}
In it's most simple form the specific characters in the URL can change something in the arduino. Say we are controlling three lights. We can check if the first character of the URL is '1' turn the first light on; '0' for off. The same occurs with the second character for the second light, third character for the third, etc. If you are interested, I have basically done this here but the crux of the code would be
if (URL[1] == '1')
digitalWrite(ledPin1, true);
if (URL[1] == '0')
digitalWrite(ledPin1, false);
if (URL[2] == '1')
digitalWrite(ledPin2, true);
if (URL[2] == '0')
digitalWrite(ledPin2, false);
Now before I move on we'll have to talk a little bit about the URL array. It starts at 0, ends at (I'm guessing) 255. We don't know how long it is in the code but being a C string it's end will be denoted by '%5C0'. We can't really use the 0th element however because this will generally be taken up by a / to finish the server part of the URL eg the / at the end of "http://www.google.com/". When we are doing proper processing there will also be a ?variable= sort of set up.
So on to my text parsing. First we need to check if the URL being requested is to generate the index page (URL will be basically empty), or if the user is trying to add a new message from the form. This is done in the line
"if (StrCmp(URL, "?MESSAGE=", 1, 9) == true)"
Basically if the characters 1-9 in the URL are "?MESSAGE=" then we are expecting the user is trying to add a message. And why this specific string? because I said so on the form in the index page:
<form action='/' method='get'>
<input type='text' name='MESSAGE' size='15' maxlength='40'><input type='submit' value='submit'>
</form>
This just tells the browser to set up a visual form. The page that will process the form is '/' (nothing), the method is get so print the form input in the URL. Then the variable name will be 'message' and print a submit button. The process takes this a converts it to the form /?MESSAGE=bleargh. Its a bit more complicated than that though.
The browser can't send everything exactly as it is or the browser would get confused. How would it know the difference between the column in test-server:8080/stuff.htm and if someone had just written a column after it? It fixes this by just changing anything that could be a problem (basically anything that isn't a letter or number) to a hex representation of it's ascii code. I'll slow down a bit here, so if you know about ascii and hex skip to the next paragraph. So ASCII is the American Standard Code for Information Interchange. Computers don't talk in text; they talk in numbers. We make them talk in text by simply asssigned each letter (upper, lower), number, punctuation and a few other things to a specific number. View them all at http://www.asciitable.com/. Hex is the base 16 representation of that number. We count decimally (by 10) but computers count in twos (binary 0s and 1s). Because of this it is more efficient to count in a numbers of twos. Base 16 counts to 16 rather than 10 (0 1 2 3 4 5 6 7 8 9 A B C D E F), so decimal 16 is hex 10. The easiest way to figure it is just to look at the web site above and look at the dec and Hx columns. When the browser finds a character it doesn't like it swaps it for %Hex ie ' ' normally changes to %20, '(' to %28. Space is different; if the browser is working correctly it should be written as a '+'. Of course they don't have to be bad characters. http://www.%67%6F%6f%67%6c%65.com should take you to google.com. Edit: the browser seems to convert automatically if you look at the status bar at the bottom of he screen. Know that the above link is pointing to the exact web address displayed.
But I digress. Having figured that a URL does contain a message the sketch needs to convert the above hex representations and strange characters back to characters that we can display. It does this by looping through each letter and looking for the % sign that would say the character needs to be converted.
do
{
loopLetterFound = false;
if (SERIALOUT) Serial.print(urlIndex);
if (urlIndex < (urlLen - 2))
{
//begin quick and dirty encoding parser
if (URL[urlIndex] == '%') //encoding makes non viable characters into %hh where hh is
{ //the characters hex value.
if (SERIALOUT) Serial.println("Will test hex");
tmpChar = HexToInt(URL[urlIndex + 1], URL[urlIndex + 2]);
if (tmpChar != -1)
{
messages[0][messageIndex] = tmpChar;
loopLetterFound = true;
urlIndex += 2;
}
else //problem occured with hex conversion.
{
messages[0][messageIndex] = '%';
loopLetterFound = true;
urlIndex += 2;
}
}
}
}
So:
- If it is a '+' add a ' ' to the message.
- If it is a % convert the next two characters to a character and add it to the message
- Otherwise just add the character to the message.
HexToInt just plays with the maths behind base 16 so that it can be converted back to base 10. From here we can cast as a char (character) if it isn't one already to turn it into the corresponding character. If the base 16 stuff still hurts or you want to better understand the hex2int function this website explains base 16 reasonably well.
0 comments:
Post a Comment