#!/usr/bin/perl -w
use strict;
use RRDs;

my $rrd = '/var/lib/rrd';
my $img = '/var/www/localhost/htdocs/rrdtool/hardware';

&ProcessSensors("sensors");
# process data for each specified HDD (add/delete as required)
&ProcessHDD("sda", "160GB Samsung");

sub ShowErr
{
	if (my $err = RRDs::error) {
		print "$0: failed to create rrd: $err\n";
	}
}

sub ProcessSensors
{
	my $name = shift;

	print "Hardware Sensors\n";

	my $in = `sensors`;
	my ($core0) = ($in =~ /Core0 Temp:.*\n\s+\+(\d{1,2})\D{2}C/);
	my ($core1) = ($in =~ /Core1 Temp:.*\n\s+\+(\d{1,2})\D{2}C/);
	my ($vcore) = ($in =~ /VCore:\s+\+(\d{1,2}\.\d{2}) V/);
	my ($v12) = ($in =~ /\+12V:\s+\+(\d{1,2}\.\d{2}) V/);
	my ($v33) = ($in =~ /\+3\.3V:\s+\+(\d{1,2}\.\d{2}) V/);
	my ($v5) = ($in =~ /\+5V:\s+\+(\d{1,2}\.\d{2}) V/);
	my ($vm12) = ($in =~ /-12V:\s+\+(\d{1,2}\.\d{2}) V/);
	my ($v5sb) = ($in =~ /V5SB:\s+\+(\d{1,2}\.\d{2}) V/);
	my ($cpufan) = ($in =~ /CPU Fan:\s+(\d{3,5}) RPM/);
	my ($mbtemp) = ($in =~ /M\/B Temp:\s+\+(\d{1,2})\D{2}C/);
	my ($cputemp) = ($in =~ /CPU Temp:\s+\+(\d{1,2}\.\d)\D{2}C/);
	my ($ambtemp) = ($in =~ /temp3:\s+\+(\d{1,2}\.\d)\D{2}C/);

	print "core0: $core0, core1: $core1, vcore: $vcore\n";
	print "v12: $v12, v33: $v33, v5: $v5, vm12: $vm12, v5sb: $v5sb\n";
	print "cpufan: $cpufan\n";
	print "mbtemp: $mbtemp, cputemp: $cputemp, ambtemp: $ambtemp\n";

	if (! -e "$rrd/$name.rrd")
	{
	print "creating rrd database for $name...\n";
	RRDs::create "$rrd/$name.rrd",
		"-s 300",
		"DS:core0:GAUGE:600:U:U",
		"DS:core1:GAUGE:600:U:U",
		"DS:vcore:GAUGE:600:U:U",
		"DS:v12:GAUGE:600:U:U",
		"DS:v33:GAUGE:600:U:U",
		"DS:v5:GAUGE:600:U:U",
		"DS:vm12:GAUGE:600:U:U",
		"DS:v5sb:GAUGE:600:U:U",
		"DS:cpufan:GAUGE:600:U:U",
		"DS:mbtemp:GAUGE:600:U:U",
		"DS:cputemp:GAUGE:600:U:U",
		"DS:ambtemp:GAUGE:600:U:U",
		"RRA:AVERAGE:0.5:1:576",
		"RRA:AVERAGE:0.5:6:672",
		"RRA:AVERAGE:0.5:24:732",
		"RRA:AVERAGE:0.5:144:1460";
	}
	&ShowErr();

	RRDs::update "$rrd/$name.rrd",
		"-t", "core0:core1:vcore:v12:v33:v5:vm12:v5sb:cpufan:mbtemp:cputemp:ambtemp",
		"N:$core0:$core1:$vcore:$v12:$v33:$v5:$vm12:$v5sb:$cpufan:$mbtemp:$cputemp:$ambtemp";
	&ShowErr();

	my @intervals = ('day', 'week', 'month', 'year');
	foreach my $time (@intervals) {
	   &CreateSensorGraph($name, $time);
	}
}

sub ProcessHDD
{
	my ($name, $desc) = @_;

	my $temp=`/usr/sbin/hddtemp -n /dev/$name`;
	$temp =~ s/[\n ]//g;
	
	print "$desc (/dev/$name) temp: $temp degrees C\n";

	if (! -e "$rrd/$name.rrd")
	{
	print "creating rrd database for /dev/$name...\n";
	RRDs::create "$rrd/$name.rrd",
		"-s 300",
		"DS:temp:GAUGE:600:0:100",
		"RRA:AVERAGE:0.5:1:576",
		"RRA:AVERAGE:0.5:6:672",
		"RRA:AVERAGE:0.5:24:732",
		"RRA:AVERAGE:0.5:144:1460";
	&ShowErr();
	}

	RRDs::update "$rrd/$name.rrd",
		"-t", "temp",
		"N:$temp";
	&ShowErr();

	my @intervals = ('day', 'week', 'month', 'year');
	foreach my $time (@intervals) {
	    &CreateHDDGraph($name, $time, $desc);
	}
}

sub CreateSensorGraph
{
	my ($name, $interval) = @_;

	RRDs::graph "$img/$interval/core_temps.png",
		"--lazy",
		"-s -1$interval",
		"-t Core Temperatures",
		"-h", "80", "-w", "600",
		"-a", "PNG",
		"-v degrees C",
		"DEF:temp0=$rrd/$name.rrd:core0:AVERAGE",
		"DEF:temp1=$rrd/$name.rrd:core1:AVERAGE",
		"LINE2:temp0#0000FF:Core 0",
		"GPRINT:temp0:MIN:  Min\\: %2.lf",
		"GPRINT:temp0:MAX: Max\\: %2.lf",
		"GPRINT:temp0:AVERAGE: Avg\\: %4.1lf",
		"GPRINT:temp0:LAST: Current\\: %2.lf degrees C\\n",
		"LINE2:temp1#00FF00:Core 1",
		"GPRINT:temp1:MIN:  Min\\: %2.lf",
		"GPRINT:temp1:MAX: Max\\: %2.lf",
		"GPRINT:temp1:AVERAGE: Avg\\: %4.1lf",
		"GPRINT:temp1:LAST: Current\\: %2.lf degrees C";
	&ShowErr();

	RRDs::graph "$img/$interval/temps.png",
		"--lazy",
		"-s -1$interval",
		"-t Motherboard Temperatures",
		"-h", "80", "-w", "600",
		"-a", "PNG",
		"-v degrees C",
		"DEF:ctemp=$rrd/$name.rrd:cputemp:AVERAGE",
		"DEF:mtemp=$rrd/$name.rrd:mbtemp:AVERAGE",
		"DEF:atemp=$rrd/$name.rrd:ambtemp:AVERAGE",
		"LINE2:ctemp#0000FF:CPU",
		"GPRINT:ctemp:MIN:  Min\\: %2.lf",
		"GPRINT:ctemp:MAX: Max\\: %2.lf",
		"GPRINT:ctemp:AVERAGE: Avg\\: %4.1lf",
		"GPRINT:ctemp:LAST: Current\\: %2.lf degrees C\\n",
		"LINE2:mtemp#00FF00:Mobo",
		"GPRINT:mtemp:MIN:  Min\\: %2.lf",
		"GPRINT:mtemp:MAX: Max\\: %2.lf",
		"GPRINT:mtemp:AVERAGE: Avg\\: %4.1lf",
		"GPRINT:mtemp:LAST: Current\\: %2.lf degrees C\\n",
		"LINE2:atemp#FF0000:Ambient",
		"GPRINT:atemp:MIN:  Min\\: %2.lf",
		"GPRINT:atemp:MAX: Max\\: %2.lf",
		"GPRINT:atemp:AVERAGE: Avg\\: %4.1lf",
		"GPRINT:atemp:LAST: Current\\: %2.lf degrees C";
	&ShowErr();
		
	RRDs::graph "$img/$interval/cpufan.png",
		"--lazy",
		"-s -1$interval",
		"-t CPU Fan Speed",
		"-h", "80", "-w", "600",
		"-a", "PNG",
		"-v RPM",
		"DEF:cpufan=$rrd/$name.rrd:cpufan:AVERAGE",
		"LINE2:cpufan#0000FF:CPU Fan Speed",
		"GPRINT:cpufan:MIN:  Min\\: %2.lf",
		"GPRINT:cpufan:MAX: Max\\: %2.lf",
		"GPRINT:cpufan:AVERAGE: Avg\\: %4.1lf",
		"GPRINT:cpufan:LAST: Current\\: %2.lf RPM";
	&ShowErr();
	
	RRDs::graph "$img/$interval/volts.png",
		"--lazy",
		"-s -1$interval",
		"-t Voltages",
		"-h", "240", "-w", "600",
		"-a", "PNG",
		"-v volts",
		"DEF:v33=$rrd/$name.rrd:v33:AVERAGE",
		"DEF:v5=$rrd/$name.rrd:v5:AVERAGE",
		"DEF:vm12=$rrd/$name.rrd:vm12:AVERAGE",
		"DEF:v5sb=$rrd/$name.rrd:v5sb:AVERAGE",
		"LINE2:v33#FF0000:3.3V",
		"GPRINT:v33:MIN:  Min\\: %4.3lf",
		"GPRINT:v33:MAX: Max\\: %4.3lf",
		"GPRINT:v33:AVERAGE: Avg\\: %4.3lf",
		"GPRINT:v33:LAST: Current\\: %4.3lf volts\\n",
		"LINE2:v5#FF00FF:5V",
		"GPRINT:v5:MIN:  Min\\: %4.3lf",
		"GPRINT:v5:MAX: Max\\: %4.3lf",
		"GPRINT:v5:AVERAGE: Avg\\: %4.3lf",
		"GPRINT:v5:LAST: Current\\: %4.3lf volts\\n",
		"LINE2:vm12#00FFFF:-12V",
		"GPRINT:vm12:MIN:  Min\\: %4.2lf",
		"GPRINT:vm12:MAX: Max\\: %4.2lf",
		"GPRINT:vm12:AVERAGE: Avg\\: %4.2lf",
		"GPRINT:vm12:LAST: Current\\: %4.2lf volts\\n",
		"LINE2:v5sb#FFFF00:Southbridge",
		"GPRINT:v5sb:MIN:  Min\\: %4.3lf",
		"GPRINT:v5sb:MAX: Max\\: %4.3lf",
		"GPRINT:v5sb:AVERAGE: Avg\\: %4.3lf",
		"GPRINT:v5sb:LAST: Current\\: %4.3lf volts";
	&ShowErr();

	RRDs::graph "$img/$interval/cpu_volts.png",
		"--lazy",
		"-s -1$interval",
		"-t CPU Core Voltage",
		"-h", "80", "-w", "600",
		"-a", "PNG",
		"-v volts",
		"DEF:vcore=$rrd/$name.rrd:vcore:AVERAGE",
		"LINE2:vcore#0000FF:CPU",
		"GPRINT:vcore:MIN:  Min\\: %4.3lf",
		"GPRINT:vcore:MAX: Max\\: %4.3lf",
		"GPRINT:vcore:AVERAGE: Avg\\: %4.3lf",
		"GPRINT:vcore:LAST: Current\\: %4.3lf volts";
	&ShowErr();
	
	RRDs::graph "$img/$interval/12v.png",
		"--lazy",
		"-s -1$interval",
		"-t 12V Rail",
		"-h", "80", "-w", "600",
		"-a", "PNG",
		"-v volts",
		"DEF:v12=$rrd/$name.rrd:v12:AVERAGE",
		"LINE2:v12#00FF00:12V",
		"GPRINT:v12:MIN:  Min\\: %4.2lf",
		"GPRINT:v12:MAX: Max\\: %4.2lf",
		"GPRINT:v12:AVERAGE: Avg\\: %4.2lf",
		"GPRINT:v12:LAST: Current\\: %4.2lf volts";
	&ShowErr();
}

sub CreateHDDGraph
{
	my ($name, $interval, $desc) = @_;

	RRDs::graph "$img/$interval/$name.png",
		"--lazy",
		"-s -1$interval",
		"-t hdd temperature :: $desc (/dev/$name)",
		"-h", "80", "-w", "600",
		"-a", "PNG",
		"-v degrees C",
		"DEF:temp=$rrd/$name.rrd:temp:AVERAGE",
		"LINE2:temp#0000FF:$desc (/dev/$name)",
		"GPRINT:temp:MIN:  Min\\: %2.lf",
		"GPRINT:temp:MAX: Max\\: %2.lf",
		"GPRINT:temp:AVERAGE: Avg\\: %4.1lf",
		"GPRINT:temp:LAST: Current\\: %2.lf degrees C\\n";
	&ShowErr();
}

