The arduino code:
#define IR_SONY
#include <IRrecv.h>
#include <LiquidCrystal.h>
#include <Beeper.h>
#include <Date.h>
#include <WiServer.h>
#include <WString.h>
//wifi stuff
unsigned char local_ip[] = {192,168,1,201}; //IP address of WiShield
uint8 server_ip[] = {192,168,1,200}; //destination IP
unsigned char gateway_ip[] = {192,168,1,1}; //router or gateway IP address
unsigned char subnet_mask[] = {255,255,255,0}; //subnet mask for the local network
const prog_char ssid[] PROGMEM = {"ssid"}; //the ssid of the network to connect to, max 32 bytes
unsigned char security_type = 3; //the security type: 0 - open; 1 - WEP; 2 - WPA; 3 - WPA2
const prog_char security_passphrase[] PROGMEM = {"pass"}; //wpa/wpa2 passphrase
unsigned char wireless_mode = 1; //use infrastructure based wifi, use 2 to use ad-hoc
GETrequest getAlarmUpdate = GETrequest(server_ip, 80, "192.168.1.200", "/arduino.php");
GETrequest getTimeSynchronisation = GETrequest(server_ip, 80, "192.168.1.200", "/arduino.php?sync=1");
prog_uchar wep_keys[0];
unsigned char ssid_len;
unsigned char security_passphrase_len;
//initialize the library objects
LiquidCrystal lcd = LiquidCrystal(19, 18, 17, 16, 15, 14);
IRrecv ir = IRrecv(6);
Beeper bp = Beeper(8, 9);
Date date = Date();
//constants
const unsigned int RemoteBounceInterval = 200; //200 millisecond debounce time for remote control signals, accept only one button press each 200 milliseconds
const unsigned long ServerUpdateInterval = 60000; //check the server for an update each 60k milliseconds, in other words.. every minute
const unsigned long ServerTimeSyncInterval = 43200000; //synchronise the time with the server every 12 hours (12*60*60 = 43200), this interval is in milliseconds
//variables used in the application
boolean alarmSet = false; //whether the alarm is currently ringing (true) or not (false)
unsigned int alarmMoment[] = {61, 0, 0, 1, 1, 0}; //the next timestamp when the alarm should ring, 61 seconds cannot be achieved.. thus it won't ring
unsigned long remotePreviousTime = 0; //the previous time when a IR remote command has been processed
unsigned long updateDatePreviousTime = 0; //the previous time when the date has been updated, includes an update of the LCD
unsigned long serverUpdatePreviousTime = 0; //the last time an update from the server was requested
unsigned long previousTimeSyncTime = 0; //the last time a time synchronisation took place
boolean allowServerUpdates = true;
byte pastHeaders = 0; //the state machine variable to check whether the HTTP headers have been ignored yet, at 4 the headers are finished
byte emailCount = 0; //the number of unread emails in the inbox
String contents(30); //the contents of the HTTP request, minus the headers
void setup()
{
lcd.begin(20, 4);
lcd.clear();
Serial.begin(9600);
lcd.setCursor(0, 0);
lcd.print("Connecting to wifi..");
WiServer.init(NULL);
getAlarmUpdate.setReturnFunc(parseServerData);
getTimeSynchronisation.setReturnFunc(parseServerData);
getTimeSynchronisation.submit();
lcd.clear();
ir.enableIRIn();
bp.singleBeep();
}
void loop()
{
unsigned long time = millis();
//execute time based functions
updateDate(time);
bp.beep(time);
//check input objects
remote(time);
//see if the next alarm moment has been, if it hasn't allready been triggered
if((!alarmSet)&&(date.hasBeen(alarmMoment[0], alarmMoment[1], alarmMoment[2], alarmMoment[3], alarmMoment[4], alarmMoment[5])))
{
allowServerUpdates = false;
alarmSet = true;
bp.doubleBeep(true);
}
//run objects, let them work out their time delayed actions
serverUpdates(time);
WiServer.server_task();
delay(1);
}
void remote(unsigned long time)
{
int key = ir.decode();
if((time-remotePreviousTime) >= RemoteBounceInterval)
{
if(key >= 0)
{
remotePreviousTime = time;
if(bp.isBeeping())
{
//if the alarm is going off, stop it
bp.stopBeep();
if(key != 2704)
{
alarmMoment[0] = date.getSecond();
alarmMoment[1] = date.getMinute();
alarmMoment[2] = date.getHour();
alarmMoment[3] = date.getDay();
alarmMoment[4] = date.getMonth();
alarmMoment[5] = date.getYear();
date.addToDateTime(540, alarmMoment[0], alarmMoment[1], alarmMoment[2], alarmMoment[3], alarmMoment[4], alarmMoment[5]); //9 minute snooze
alarmSet = false; //reset the alarm
}
else
{
allowServerUpdates = true;
}
}
else
{
Serial.println(key, DEC);
}
}
}
}
void updateDate(unsigned long time)
{
if(time-updateDatePreviousTime >= 1000)
{
//previousTime = time;
updateDatePreviousTime += 1000; //keep the discrepency so it can be corrected
date.tick();
lcd.setCursor(0, 0);
char number = date.getHour();
if(number < 10) { lcd.print(' '); }
lcd.print(number, DEC);
lcd.print(':');
number = date.getMinute();
if(number < 10) { lcd.print('0'); }
lcd.print(number, DEC);
lcd.print(':');
number = date.getSecond();
if(number < 10) { lcd.print('0'); }
lcd.print(number, DEC);
if(date.getMonth() < 10) { lcd.print(' '); }
lcd.print(" ");
number = date.getDay();
if(number < 10) { lcd.print(' '); }
lcd.print(number, DEC);
lcd.print('/');
lcd.print(date.getMonth(), DEC);
lcd.print("/2");
number = date.getYear();
if(number < 100) { lcd.print('0'); }
if(number < 10 ) { lcd.print('0'); } //since it is currently 2010, this will never happen.. but it defaults to 0, so keep it in here
lcd.print(number, DEC);
lcd.setCursor(0, 1);
number = alarmMoment[2];
if(number < 10) { lcd.print(' '); }
lcd.print(number, DEC);
lcd.print(':');
number = alarmMoment[1];
if(number < 10) { lcd.print('0'); }
lcd.print(number, DEC);
lcd.print(':');
number = alarmMoment[0];
if(number < 10) { lcd.print('0'); }
lcd.print(number, DEC);
if(alarmMoment[4] < 10) { lcd.print(' '); }
lcd.print(" ");
number = alarmMoment[3];
if(number < 10) { lcd.print(' '); }
lcd.print(number, DEC);
lcd.print('/');
lcd.print(alarmMoment[4], DEC);
lcd.print("/2");
number = alarmMoment[5];
if(number < 100) { lcd.print('0'); }
if(number < 10 ) { lcd.print('0'); } //since it is currently 2010, this will never happen.. but it defaults to 0, so keep it in here
lcd.print(number, DEC);
lcd.setCursor(0, 2);
lcd.print(emailCount, DEC);
lcd.print(" unread e-mails");
}
}
void serverUpdates(unsigned long time)
{
if((allowServerUpdates)&&((time-previousTimeSyncTime) >= ServerTimeSyncInterval))
{
//do a time synchronisation with the server
serverUpdatePreviousTime = time;
previousTimeSyncTime = time;
getTimeSynchronisation.submit();
}
else
if((time-serverUpdatePreviousTime) >= ServerUpdateInterval)
{
//get an update from the server
serverUpdatePreviousTime = time;
getAlarmUpdate.submit();
}
}
void parseServerData(char* data, int len)
{
char current;
while(len-- > 0)
{
current = *(data++);
if((current == 13)||(current == 10))
{
pastHeaders += 1;
}
else
if(pastHeaders >= 3)
{
//reset the printing if its the semicolon terminator
if(current == ';')
{
pastHeaders = 0;
processServerUpdate();
contents = "";
}
else
{
contents.append(current);
Serial.print(current);
}
}
else
{
pastHeaders = 0;
contents = "";
}
}
}
Due to post size constraints, the final function has been cut-off, it is listed in the next post.
Also, my apologies for awkward alignments, as this was written mainly in the arduino IDE.. some actual tab characters made it in. The alignments should be fixed if you view it with a tab size of 2.