I have been having trouble with some web servers going down on me in the middle of the night. I decided I had enough, and am going to make a Server Up-time Monitor. Now, I could dust off one of the old computers I got laying around here (heaven knows I got enough of them), install Linux, and Nagios, but I want the monitor to wake me up in the middle of the night and consume VERY little power.
I decided to build it based of a Rabbit-Semiconductor RabbitCore RCM3100 embedded Micro-controller. This devise is small -about the size of a pack of gum, uses very little power do to it’s size, and can be made to actually DO things, like control X-10 power modules or directly run relays, sound alarms, play .wav files, etc.
Phase 1 is to make it work.
Phase 2 is to make it useful.
Phase 3 is to make it indispensable.
I have completed phase 1 tonight.
I wrote some code, based off of the samples that came with the Ethernet Starter Kit I bought a while ago, and am using to make my automatic fish feeder.
Basically, all it does is ping the server once a minute. If the server fails to reply to the ping 5 times in a row, an email is generated. This will be sent to the email address for my cell phone, effectively paging me.
Some things to make this ‘useful’ and ‘indispensable’. Here is a simple list of what I am thinking it could and should do:
- Check multiple web servers
- Page multiple people’s cell phones.
- Check actual HTTP service by loading a web page and making sure it’s what is expected.
- Display a simple ‘status’ by some method – a red & green LED display panel, LCD display, etc.
- Turn on the night light in my bedroom at night
- Turn on an alarm
- Play a wave file that indicates the current status
I am going to publish my Dynamic C code, and any future updates, here to my blog in case this is useful to anybody else.
Please feel free to leave any comments/questions/patches/etc.
/*******************************************************************************
Web Server Montitor
Author Mike Creuzer
mike.creuzer.com
Based from the RabbitCore sample files:
Samplestcpipping.c
Z-World, 2000
ICMP demonstration, by pinging a remote host.
Prints a message when the ping response arrives here.
If PING_WHO is not defined, then it pings the default
gateway.
smtp.c
Z-World, 2000
A small program that uses the SMTP library
to send an e-mail.
*******************************************************************************/
/***********************************
* Configuration *
* ------------- *
* All fields in this section must *
* be altered to match your local *
* network settings. *
***********************************/
/*
* Pick the predefined TCP/IP configuration for this sample. See
* LIBRARIESTCP_IPTCP_CONFIG.LIB for instructions on how to set the
* configuration.
*/
#define TCPCONFIG 1
/** Remote interface to send PING to (passed to resolve()): **/
/* Undefine to retrieve default gateway and ping that. */
#define PING_WHO "mike.creuzer.com"
#define FROM "[email protected]"
#define TO "[email protected]"
#define SUBJECT "Monitor Update"
#define DOWNBODY "Server is down."
#define UPBODY "Server is back up."
/*
* The SMTP_SERVER macro tells DCRTCP where your mail server is. This
* mail server MUST be configured to relay mail for your controller.
*
* This value can be the name or the IP address.
*/
/*
* The SMTP_SERVER macro tells DCRTCP where your mail server is. This
* mail server MUST be configured to relay mail for your controller.
*
* This value can be the name or the IP address.
*/
#define SMTP_SERVER "smtp-server.tampabay.rr.com"
/*
* The SMTP_DOMAIN should be the name of your controller. i.e.
* "somecontroller.somewhere.com" Many SMTP servers ignore this
* value, but some SMTP servers use this field. If you have
* problems, turn on the SMTP_DEBUG macro and see were it is
* bombing out. If it is in the HELO command consult the
* person in charge of the mail server for the appropriate value
* for SMTP_DOMAIN. If you do not define this macro it defaults
* to the value in MY_IP_ADDRESS.
*
*/
#define SMTP_DOMAIN "aquaria.serveblog.com"
/*
* The SMTP_VERBOSE macro logs the communications between the mail
* server and your controller. Uncomment this define to begin
* logging
*/
// #define SMTP_VERBOSE
/********************************
* End of configuration section *
********************************/
#use dcrtcp.lib
#use smtp.lib
int main()
{
longword seq,lastpingrecieved,ping_who,tmp_seq,time_out;
char buffer[100];
int down, sentdown, sentup;
sock_init();
// Wait for the interface to come up
while (ifpending(IF_DEFAULT) == IF_COMING_UP) {
tcp_tick(NULL);
}
/* Print who we are... */
printf( "My IP address is %snn", inet_ntoa(buffer, gethostid()) );
/*
* Get the binary ip address for the target of our
* pinging.
*/
#ifdef PING_WHO
/* Ping a specific IP addr: */
ping_who=resolve(PING_WHO);
if(ping_who==0) {
printf("ERROR: unable to resolve %sn",PING_WHO);
return 1;
}
#else
/* Examine our configuration, and ping the default router: */
tmp_seq = ifconfig( IF_ANY, IFG_ROUTER_DEFAULT, & ping_who, IFS_END );
if( tmp_seq != 0 ) {
printf( "ERROR: ifconfig() failed --> %dn", (int) tmp_seq );
return 1;
}
if(ping_who==0) {
printf("ERROR: unable to resolve IF_ROUTER_DEFAULTn");
return 1;
}
#endif
seq=0;
lastpingrecieved = 0;
down = 0;
sentdown = 0;
sentup = 0;
for(;;) {
/*
* It is important to call tcp_tick here because
* ping packets will not get processed otherwise.
*/
tcp_tick(NULL);
/*
* Send one ping per second.
*/
costate {
//waitfor(DelaySec(1));
waitfor(DelaySec(60));
_ping(ping_who,seq++);
}
/*
* Has a ping come in? time_out!=0xfffffff->yes.
*/
time_out=_chk_ping(ping_who,&tmp_seq);
if(time_out!=0xffffffff){
if(down == 1){
printf("Service has been restored. n");
down = 0;
smtp_sendmail(TO, FROM, SUBJECT, UPBODY);
while(smtp_mailtick()==SMTP_PENDING)
continue;
if(smtp_status()==SMTP_SUCCESS)
printf("Message sentn");
else
printf("Error sending messagen");
}
printf("Received Ping: %ld %ldn", tmp_seq, time_out);
lastpingrecieved = tmp_seq;
sentdown = 0;
}else
{
if (seq - lastpingrecieved >= 5 && sentdown == 0){
printf("Host Unavailable. n");
down = 1;
sentdown = 1;
smtp_sendmail(TO, FROM, SUBJECT, DOWNBODY);
while(smtp_mailtick()==SMTP_PENDING)
continue;
if(smtp_status()==SMTP_SUCCESS)
printf("Message sentn");
else
printf("Error sending messagen");
}
}
} // end FOR
}