Essentially, you want a certain action occurs if the garage door has changed state. It sounds like your Arduino is set up as an I/O register of sorts, where you can read its current position, or write a new position. Since I should be working on Embedded System Design homework and am instead procrastinating, here's a state machine.

I think the Arduino is actually the easier place to put the state machine, because otherwise you have to deal with all the orchestrations required to maintain less than 8 bits of state in a stateless HTTP-based system. When STATUS changes, have it send a signal to the RPi that causes it to e-mail you or whatever. I'd also set up a mechanism on the Arduino to query STATUS, as well as set or clear the ARMED flag... a RESET is probably also a good idea (when this happens, go straight back to START).
Note: I haven't tested this code, nor have I written a state machine in C before. God help you.
Code:
typedef enum {ST_IDLE, ST_OPEN, ST_WAIT, ST_ALARMING} state_t;
typedef enum {ALLCLEAR, PANIC, DUMBADOLLARSIGNDOLLARSIGN} status_t;
typedef enum {false = 0, true} bool; // good god, what a barbaric language
state_t currentState = ST_IDLE;
status_t currentDoorStatus = ALLCLEAR;
const unsigned long OPEN_WAIT = 5 * 60 * 1000; // milliseconds to wait when the barn door is open
unsigned long open_millis = 0; // millis() when door is detected open
bool armed = false; // set this to true if you want to PANIC
// prototypes for implementation-specific stuff
void sendNotification(status_t alarmStatus);
bool isGarageDoorOpen();
// setStatus: calls sendNotification when newStatus is different than currentDoorStatus
void setStatus(status_t newStatus)
{
if (newStatus != currentDoorStatus)
{
// the status has changed; send a text message or e-mail or whatever
sendNotification(newStatus);
currentDoorStatus = newStatus;
}
return;
}
// loop: this is the code that loops over and over and over again
void loop()
{
switch (currentState)
{
case ST_IDLE:
if (true == isTheGarageDoorOpen())
{
// garage door is open; proceed to open state
currentState = ST_OPEN;
}
else
{
// garage door is closed; all clear, stay in idle state
setStatus(ALLCLEAR);
currentState = ST_IDLE;
}
break;
case ST_OPEN:
if (true == armed)
{
// alarm is armed, freak all the way out, proceed to alarming state
setStatus(PANIC);
currentState = ST_ALARMING;
}
else
{
// alarm is not armed, record current time, proceed to wait state
open_millis = millis(); // record the current time
currentState = ST_WAIT;
}
break;
case ST_WAIT:
if (OPEN_WAIT < (millis() - open_millis))
{
if (true == isTheGarageDoorOpen())
{
// door has been open more than OPEN_WAIT milliseconds, update status and proceed to alarming state
setStatus(DUMBADOLLARSIGNDOLLARSIGN);
currentState = ST_ALARMING;
}
else
{
// miracles of miracles; the damn thing is now closed. back to idle state
currentState = ST_IDLE;
}
}
else
{
// continue waiting...
currentState = ST_WAIT;
}
break;
case ST_ALARMING:
if (false == isTheGarageDoorOpen())
{
// garage door has closed, return to idle state
currentState = ST_IDLE;
}
else
{
// we're still freaking out over here
currentState = ST_ALARMING;
}
break;
}
}
Edit: So apparently I hallucinated the bool type; I tend to do that. Have another enum.
_________________
Code:
/* TODO: need to add signature to posts */