Skip to content

Instantly share code, notes, and snippets.

@mrchrisadams
Created April 25, 2009 08:06
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mrchrisadams/101553 to your computer and use it in GitHub Desktop.
Save mrchrisadams/101553 to your computer and use it in GitHub Desktop.
//////////////////////////////////////////////////////////////////////////
// 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