Created
April 25, 2009 08:06
-
-
Save mrchrisadams/101553 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
////////////////////////////////////////////////////////////////////////// | |
// Tea Light source code, largely cut and pasted from existing code on // | |
// the web // | |
// // | |
// The majority of this code is based on XTalker/Bob.S's code on the // | |
// arudino forums: // | |
// http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1231812230 // | |
// // | |
// String parsing C code from JeffTanner: // | |
// http://www.daniweb.com/forums/showthread.php?p=640773 // | |
// // | |
// What's left (all 5 lines of it..) by James Gardner // | |
// (http://jimmyg.org) and Chris Adams (http://chrisadams.me.uk) // | |
// // | |
// Public domain: use responsibly, have fun! // | |
////////////////////////////////////////////////////////////////////////// | |
// Include description files for other libraries used (if any) | |
#include <string.h> | |
#include <Ethernet.h> | |
#include <stdlib.h> | |
#include "Wire.h" | |
#include "BlinkM_funcs.h" | |
// | |
// We need a converter to parse the frequency of the grid. | |
// | |
bool string_to_float( char str[], float &number ) | |
{ | |
char num; | |
double div=1; | |
number=0; | |
int i=0, decimal=0; | |
bool p=false; | |
while (str[i] != '\0') | |
{ | |
num=str[i]; | |
if ( (num=='0') | |
||(num=='1') | |
||(num=='2') | |
||(num=='3') | |
||(num=='4') | |
||(num=='5') | |
||(num=='6') | |
||(num=='7') | |
||(num=='8') | |
||(num=='9') | |
) | |
{ | |
number=number*10; | |
number=number+float(num-'0'); | |
} | |
else if (num=='.' && !p) | |
{ | |
p=true; | |
i++; | |
continue; | |
} | |
if (p) | |
{ | |
decimal++; | |
} | |
i++; | |
} | |
if ( p ) | |
{ | |
for (int j=0;j<decimal;j++) | |
{ | |
div=div*10; | |
} | |
} | |
number=number/div; | |
return true; | |
} | |
// | |
// Let's set up the ethernet shield | |
// | |
// Ethernet vars | |
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }; | |
byte ip[] = { 10, 10, 63, 219 }; // local ip for the tealight | |
byte server[] = { 89, 16, 186, 36 }; // caniturniton.com | |
// Start Cthernet client | |
Client client(server, 80); | |
// This is the function which gets called when the Arduino turns on | |
void setup() | |
{ | |
// Set up a serial connection to the IDE for debugging | |
Serial.begin(9600); | |
// Send some messages to the Arduino IDE | |
Serial.println("Starting WebWx"); | |
Serial.println("connecting..."); | |
// Set up the Ethernet sheild | |
Ethernet.begin(mac, ip); | |
// Wait for a second | |
delay(1000); | |
// Implement a very simple HTTP client | |
if (client.connect()) { | |
Serial.println("connected"); | |
client.println("GET /api/xml HTTP/1.0"); | |
client.println("Host: caniturniton.com"); | |
client.println(); | |
// Give the server 2 seconds to respond | |
delay(2000); | |
// The server response is handled in loop() | |
} else { | |
Serial.println("connection failed"); | |
} | |
// Initialise the BlinkM | |
BlinkM_beginWithPower(); | |
BlinkM_stopScript( 0 ); // turn off startup script | |
} | |
// This function gets called constantly as fast as the Arduino can call it | |
// it is only the delay() calls which prevent it getting called hundreds of | |
// times a second | |
void loop() { | |
// Read serial data in from web: | |
while (client.available()) { | |
// Process the XML | |
serialEvent(); | |
} | |
if (!client.connected()) { | |
Serial.println(); | |
Serial.println("Disconnected"); | |
client.stop(); | |
// Time until next update | |
Serial.println("Waiting"); | |
for (int t = 1; t <= 15; t++) { | |
Serial.println("Tea minus: "); | |
Serial.println(16 - t); | |
delay(1000); | |
} | |
Serial.println("finished waiting"); | |
if (client.connect()) { | |
// Get the latest update from caniturniton.com | |
Serial.println("Reconnected"); | |
client.println("GET /api/xml HTTP/1.0"); | |
client.println("Host: caniturniton.com"); | |
client.println(); | |
delay(2000); | |
} else { | |
Serial.println("Reconnect failed"); | |
} | |
} | |
} | |
// | |
// Now we need some code capable of parsing the very simple XML feed | |
// | |
// Max string length may have to be adjusted depending on data to be extracted | |
#define MAX_STRING_LEN 20 | |
// Setup vars | |
char tagStr[MAX_STRING_LEN] = ""; | |
char dataStr[MAX_STRING_LEN] = ""; | |
char tmpStr[MAX_STRING_LEN] = ""; | |
char endTag[3] = {'<', '/', '\0'}; | |
int len; | |
// Flags to differentiate XML tags from document elements (ie. data) | |
boolean tagFlag = false; | |
boolean dataFlag = false; | |
// Process each XML character returned | |
void serialEvent() { | |
// Read a char | |
char inChar = client.read(); | |
if (inChar == '<') { | |
addChar(inChar, tmpStr); | |
tagFlag = true; | |
dataFlag = false; | |
} else if (inChar == '>') { | |
addChar(inChar, tmpStr); | |
if (tagFlag) { | |
strncpy(tagStr, tmpStr, strlen(tmpStr)+1); | |
} | |
// Clear tmp | |
clearStr(tmpStr); | |
tagFlag = false; | |
dataFlag = true; | |
} else if (inChar != 10) { | |
if (tagFlag) { | |
// Add tag char to string | |
addChar(inChar, tmpStr); | |
// Check for </XML> end tag, ignore it | |
if ( tagFlag && strcmp(tmpStr, endTag) == 0 ) { | |
clearStr(tmpStr); | |
tagFlag = false; | |
dataFlag = false; | |
} | |
} | |
if (dataFlag) { | |
// Add data char to string | |
addChar(inChar, dataStr); | |
} | |
} | |
// If a LF, process the line | |
if (inChar == 10 ) { | |
// Find specific tags and print data. | |
// This is where we get the frequency from and where we set the colour | |
if (matchTag("<frequency>")) { | |
Serial.print("Frequency: "); | |
Serial.print(dataStr); | |
float f; | |
int red = 0; | |
int green = 0; | |
string_to_float(dataStr, f); | |
if (f > 50.0) { | |
green = 255; | |
} else { | |
red = 255; | |
} | |
Serial.print(" Red: "); | |
Serial.print(red); | |
Serial.print(" Green: "); | |
Serial.print(green); | |
// Now set the BlinkM to the correct colour | |
BlinkM_fadeToRGB(0x000, red, green, 0 ); | |
} | |
if (matchTag("<recommendation>")) { | |
Serial.print(", Recommendation: "); | |
Serial.print(dataStr); | |
// XXX Not sure about this line: | |
//client.stop(); | |
} | |
// Clear all strings | |
clearStr(tmpStr); | |
clearStr(tagStr); | |
clearStr(dataStr); | |
// Clear Flags | |
tagFlag = false; | |
dataFlag = false; | |
} | |
} | |
// Other Functions related to the XML parsing above | |
// Function to clear a string | |
void clearStr (char* str) { | |
int len = strlen(str); | |
for (int c = 0; c < len; c++) { | |
str[c] = 0; | |
} | |
} | |
//Function to add a char to a string and check its length | |
void addChar (char ch, char* str) { | |
char *tagMsg = "<TRUNCATED_TAG>"; | |
char *dataMsg = "-TRUNCATED_DATA-"; | |
// Check the max size of the string to make sure it doesn't grow too | |
// big. If string is beyond MAX_STRING_LEN assume it is unimportant | |
// and replace it with a warning message. | |
if (strlen(str) > MAX_STRING_LEN - 2) { | |
if (tagFlag) { | |
clearStr(tagStr); | |
strcpy(tagStr,tagMsg); | |
} | |
if (dataFlag) { | |
clearStr(dataStr); | |
strcpy(dataStr,dataMsg); | |
} | |
// Clear the temp buffer and flags to stop current processing | |
clearStr(tmpStr); | |
tagFlag = false; | |
dataFlag = false; | |
} else { | |
// Add char to string | |
str[strlen(str)] = ch; | |
} | |
} | |
// Function to check the current tag for a specific string | |
boolean matchTag (char* searchTag) { | |
if ( strcmp(tagStr, searchTag) == 0 ) { | |
return true; | |
} else { | |
return false; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment