Linux Reef Controller – Example Script & Cron Entry

image_pdfimage_print

This page will run through a perl script that is used on the Web Server in order to process polled data from sensors attached to Sensor Servers on your sensor network.

The script can be stored anywhere as long as it can be called by cron. It can also be reused for each sensor on your network by just making a few small modifications. This script is the heart of the project and provides sensor polling, website updates, graph generation and updating, email alerts, and logging.

#!/usr/bin/perl

#Title: Temperature Sensor Polling Example
#By: Ronny L. Bull
#Description: 
#This script is used in conjunction with a cron job in order to poll a sensor
#on a Dallas 1-wire sensor network.  The script uses the reading from the sensor
#to generate a rrd database entry and 24 hour trend graph.  It also checks the reading
#against a set of conditions and outputs the result to a file that can be included on a
#web page.  The file contains a hyperlink to the graph as well as the current reading
#for that poll cycle.  An email is generated if the reading is found to be in error
#or outside of the specified "safe" conditions.

#Keep it tight!
use strict;
use warnings;

#Use the OWFS and RRDTool modules
use OW;
use RRDs;

#RRD graph and database files
#Change the file names as appropriate for your setup
my $rrd_db = "/var/www/localhost/htdocs/RRD/example_temp.rrd";
my $rrd_graph = "/var/www/localhost/htdocs/graphs/example_temp.png";

#Mail alert flag initialzed to 0.
#Helps to prevent email spam
#Values: 0 = No Email Alert, 1 = Value Email Alert, 2 = Sensor Error Email Alert
my $mail = 0;

#Initialize the usb interface (for direct usb connection)
#OW::init('-F u');

#Initialize a network connection to a sensor server
#Set this to your sensor servers's IP and port
OW::init('-F 192.168.0.6:4304');

#Get temperature from sensor
#set this to your sensor's ID and the value you want to check
#ie. 'temperature' for temp, 'humidity' for humidity, 'vis' for solar radiation.
my $temp = (OW::get('/28.2F2840020000/temperature'));

#Close the owfs connection
OW::finish();

#If the RRD DB exists update it and create the graph
#else Create a new RRD DB, update it and create the graph
if(-e $rrd_db)
	{
		updateDB();
		createGraph();
	}
else
	{
		createDB();
		updateDB();
		createGraph();
	}

updateFile();
exit;

#Graph creation function
#For more info on RRDTool syntax see:
#http://oss.oetiker.ch/rrdtool/tut/rrd-beginners.en.html
sub createGraph
{
RRDs::graph ("$rrd_graph",
	"--title=Temperature Over 24 hrs",
	"--vertical-label=Degrees F",
	"--x-grid", 'MINUTE:10:HOUR:1:HOUR:4:0:%a:%H:%M',
	"DEF:tmp=$rrd_db:temp:AVERAGE",
	"AREA:tmp#FF0000:Temperature\\j",
	"GPRINT:tmp:LAST:Current  %4.2lf",
	"GPRINT:tmp:AVERAGE:Average  %4.2lf",
	"GPRINT:tmp:MIN:Lowest  %4.2lf",
	"GPRINT:tmp:MAX:Highest  %4.2lf\\j");

}

#RRD DB creation function
sub createDB
{
#perl way (no worky)
#RRDs::create ("$rrd_db",
#	"DS:temp:GUAGE:600:U:U",
#	"RRA:AVERAGE:0.5:1:288"); 

#system call (worky)
`rrdtool create ${rrd_db} DS:temp:GAUGE:600:U:U RRA:AVERAGE:0.5:1:288`;

}

#Update DB function
sub updateDB
{
	RRDs::update ("$rrd_db", "N:$temp");
}

#Update web include file with current temp
sub updateFile
{
my $high = "<font color=red><b>$temp F</b></font>";
my $mid = "<font color=green><b>$temp F</b></font>";
my $low = "<font color=blue><b>$temp F</b></font>";
my $error = "<font color=red><b>SENSOR ERROR</b></font>";
my $output;

#Set range values for warnings and alerts

#No reading is an error
if($temp eq "")
        {
		#Set web output to SENSOR ERROR in RED
                $output = $error;

		#Email alert
                errorAlert();
        }

#Temp of 185 is an error
elsif($temp == 185)
        {
		#Set web output to SENSOR ERROR in RED
                $output = $error;
                
		#Email alert
		errorAlert();
        }

#Temp greater than 90 and less than 185 is too hot
elsif(($temp > 90) && ($temp < 185))
        {
		#Set web output to Temp in RED
                $output = $high;

		#Email alert
		mailAlert();
        }

#Temp less than 50 is too cold
elsif($temp < 50)
        {
		#Set web output to Temp in Blue
                $output = $low;

		#Email alert
		mailAlert();
        }

#Temp >50 but <90 is just right
else
        {
		#Set web output to Temp in Green
                $output = $mid;

		#Set mail = 0; No alert
		mailLogger();
	}

#Write to web include file
#Manually include the generated file in your main report page 
#by using the php include() function
#ie. <? include("include/cur_example_temp.php");
#Change the file names and label as appropriate for your setup
open (FILE, '>/var/www/localhost/htdocs/include/cur_example_temp.php');
print FILE "<head><body><a href=graphs/example_temp.png rel=gb_image[]>Server Rack Temperature:</a> $output <br />";
close (FILE);
}

#Value alert email function
sub mailAlert
{
	#Have we sent an email temperature alert before?
        mailCheck();

	#Yes we did
        if($mail == 1)
                {
			#Still in warning so keep it flagged 
			#so we don't send another email
                        $mail = 1;
                        mailLogger();
                }

	#Nope its new
        else
                {
			#Set mail to 1 because we are sending a new email this time
                        $mail = 1;
                        mailLogger();

			#Use sendmail to send the alert
			#Change email alert and address
		        open (MAIL, "|/usr/sbin/sendmail email@address.com");
        		print MAIL "From: email@address.com\n";
        		print MAIL "Subject: Server Rack Temperature Alert!\n\n";
        		print MAIL "The temperature of the server rack in the office is $temp F";
        		close(MAIL);
		}
}

#Sensor error email alert function
sub errorAlert
{
	#Have we emailed sensor error alert before?
	mailCheck();
	
	#Yes we did
        if($mail == 2)
                {
			#Still erroring so keep it flagged
			#so we don't send another email
                        $mail = 2;
                        mailLogger();
                }

	#Nope its new
        else
                {
			#Set mail to 2 because we are sending a new email this time
                        $mail = 2;
                        mailLogger();
			
			#Use sendmail to email the alert
			#Change email alert and address
		        open (MAIL, "|/usr/sbin/sendmail email@address.com");
        		print MAIL "From: email@address.com\n";
        		print MAIL "Subject: Server Rack Temperature Sensor Error!\n\n";
        		print MAIL "There was a problem reading the server rack temperature sensor";
        		close(MAIL);
		}
}

#Email check status function
sub mailCheck
{
	#Open the log file and read the status from previous poll
	#Change file name as appropriate for your setup
        open(FILE, "/var/log/lrc/mail_log/example_temp_mail.log");
        while(<FILE>)
                {
                        $mail = $_;
                }
        close(FILE);

}

#Email log status function
sub mailLogger
{
	#Open the log file and write the new status
	#Change file name as appropriate for your setup
        open(FILE, '>/var/log/lrc/mail_log/example_temp_mail.log');
        print FILE $mail;
        close(FILE);
}

To have the script run every 5 mins setup a cron entry:

  • crontab -e
  • Append the following line to your crontab to have the script run every 5 mins:
  • */5 * * * * perl /var/www/localhost/cgi-bin/example_temp.pl \
    >/var/log/lrc/example_temp.log >/dev/null 2>&1
  • Restart Cron
    • /etc/init.d/vixie-cron restart
  • This will create a cron job that runs the script at
    /var/www/localhost/cgi-bin/example_templ.pl

    every 5 mins and logs any runtime errors to

    /var/log/lrc/example_temp.log

  1. No Comments