#!/usr/bin/perl  -w
#-----------------------------------------------------------------
# By: john@stilen.com
#
# Title:
#     sensors.rrd.pl
#
# Purpouse: 
#     Chart temp and fan stats
#     Keep fan as slow as possible given safe Target CPU Temp.
#
# To find the correct  settings, run:  pwmconfig
#     9191-0290/fan1_input     current speed: 17307 RPM
#     9191-0290/fan2_input     current speed: 17307 RPM
#     9191-0290/fan3_input     current speed: 15000 RPM
#
# Fan's controlled by: 
#   /sys/devices/platform/i2c-9191/9191-0290/pwm1
#   /sys/devices/platform/i2c-9191/9191-0290/pwm2
#
#-----------------------------------------------------------------
use strict;
#use encoding "MacRoman", STDOUT => "utf8";
use encoding "iso-8859-1", STDOUT => "utf8";
#use encoding "UTF-8", STDOUT => "utf8";
# use utf8;
use RRDs;
#-----------------------------------------------------------------
my $debug=               "0";                   # debug 1=on, 0=off
my $do_rrd=              "1";                   # rrd create/update 1=on, 0=off
my $graph=               "1";                   # graph 1=on, 0=off
my $quiet=               "0";                   # change fan speed 1=on, 0=off 
my $pause=               "0";                   # Time between tests
my $counter=             "1";                   # number of loops
my $sensors=             "/usr/bin/sensors";    # Binary for sensors
my $rrdtool=             "/usr/bin/rrdtool";    # Binary for rrdtool
my $smartctl=            "/usr/sbin/smartctl";  # Binary for smartctl
my $Sensor_string=       "smsc47b397-isa-0480"; # Header in sensors output
my $time=                time(  );
my $Speed1=              "100" ;                # Setting default fan speed.
my $TargetTmp_upper=     "44";                  # Target temp for CPU
my $TargetTmp_lower=     "42";                  # Target temp for CPU
my $ProcFile=            "/sys/devices/platform/i2c-9191/9191-1410/pwm2";
my $graph_width=         "300";
my $graph_height=        "100";
my $rrd_dir=             "/var/www/localhost/htdocs/thermal";
my $rrd_file=            "$rrd_dir/fan_temp.rrd";

my $graph_temp_file_2hr= "$rrd_dir/temp_2hr.png";
my $graph_cpu_temp_file_2hr= "$rrd_dir/cpu_temp_2hr.png";
my $graph_rpm_file_2hr=  "$rrd_dir/fan_2hr.png";
my $graph_temp_file_12hr="$rrd_dir/temp_12hr.png";
my $graph_rpm_file_12hr= "$rrd_dir/fan_12hr.png";
my $graph_temp_file_1wk= "$rrd_dir/temp_1wk.png";
my $graph_rpm_file_1wk=  "$rrd_dir/fan_1wk.png";
my $graph_temp_file_1mo= "$rrd_dir/temp_1mo.png";
my $graph_rpm_file_1mo=  "$rrd_dir/fan_1mo.png";
my $graph_temp_file_1yr= "$rrd_dir/temp_1yr.png";
my $graph_rpm_file_1yr=  "$rrd_dir/fan_1yr.png";
my $index_file=          "$rrd_dir/index.html";
my %stats=(  cpu00  => "0",
	     cpu01  => "0",
	     cpu10  => "0",
	     cpu11  => "0",
	     twa000  => "0",
	     twa001  => "0",
	     twa002  => "0",
	     twa003  => "0",
	   );
#-----------------------------------------------------------------
#
# Create data directoy if it doesn't exist
#
if ( ! -e $rrd_dir ){ 
  mkdir( $rrd_dir, 755 ) || die "Can't create data directory ($rrd_dir)\t$!\n";
}
#-----------------------------------------------------------------
my $EventDate;
open (DATE, "date|") || die "Could not run date:\t$?\n";
chomp($EventDate=<DATE>);
close (DATE);
if ($debug==1 ){  print "DATE: $EventDate\n";  }

#-----------------------------------------------------------------
# flush the buffer
$| = 1;
#-----------------------------------------------------------------
# daemonize the program
if ( $debug eq "0" ){  
    #&daemonize; 
} else {    
  use strict; 
}
#-----------------------------------------------------------------
# Number of iterations
while ( $counter ){
    #
    # Get temp
    #
    &get_i2c( \%stats ) || die "can't check sensors:\t $!\n";
    if ( $debug eq "2" ){  
        print "Contents of hash after\n";
        for my $key ( sort ( keys ( %stats ) ) ){
	  print "\t$key:\t$stats{$key}\n";
	}
    }

    if ( $quiet eq "1" ){
        #
        # Get speed
        #
        chomp ( my $Speed1 = &get_file_fanspeed );
        if ( $debug eq "1" ){  print "Speed:  $Speed1\n"; }
        #
        # Calculate new speed
        #
        my $NewSpeed=&new_fanspeed(\%stats );
        if ( $debug eq "1" ){  print "NewSpeed:  $NewSpeed\n"; }
        #
        # If Speed and NewSpeed are not equal, update fan speed file.
        #
            if ( $NewSpeed ne $Speed1 ){ 
                &update_fanspeed($NewSpeed); 
	        if ( $debug eq "1" ){  print "Loading new speed\n"; }
            }
    }
    if ( $do_rrd eq "1" ){      
        #
        # Create RRD file, if it does not exist
        #
        if ( ! -e "$rrd_file" ){
    	    &create_graph($rrd_file);  
        };
        #
	# hard drive temps
	#
	&hd_temp(\%stats);
	if ( $debug eq "1" ){ 
	    print "Just after  function: hd_temp\n";
	    for my $key ( sort ( keys( %stats ) ) ){
	        print "\t$key=$stats{$key}\n";
	    }
        }
	#
	# Populate the rrd database
	#
        my $NewSpeed=&record_fanspeed(\%stats,$rrd_file);
        #
        # Graph from rrd
        #
        &graph_fanspeed;
	
    }
    #
    # Build index.html file
    #
    &make_index;

    #
    #
    # Sleep
    #
    system ( "/bin/sleep",  "$pause" );
    #
    # Number of times we loop 
    # count down to zero from $counter
    #
    $counter--;  

} # END main while loop
#-----------------------------------------------------------------
#sub daemonize {
#    chdir '/'                  or die "Can't chdir to /: $!";
#    open STDIN, '/dev/null'    or die "Can't read /dev/null: $!";
#    open STDOUT, '>>/dev/null' or die "Can't write to /dev/null: $!";
#    open STDERR, '>>/dev/null' or die "Can't write to /dev/null: $!";
#    defined(my $pid = fork)    or die "Can't fork: $!";
#    exit if $pid;
#    setsid                     or die "Can't start a new session: $!";
#    umask 0;
#}
#-----------------------------------------------------------------
sub create_graph {
    chomp ( my $rrd_file=shift );
    # rrdtool create $rrd_directory/fan_temp.rrd \
    # --step 1 \		 # 1 sec steps for RRA's blow
    # DS:Case1:GAUGE:10:0:U \	 # DataSource: over max of 10sec, "0" minimum and unknown max value as valid data
    # DS:Case2:GAUGE:10:0:U \	 # DataSource: over max of 10sec, "0" minimum and unknown max value as valid data
    # DS:Case3:GAUGE:10:0:U \	 # DataSource: over max of 10sec, "0" minimum and unknown max value as valid data
    # DS:Rpm1:GAUGE:10:0:U \	 # DataSource: over max of 10sec, "0" minimum and unknown max value as valid data
    # DS:Rpm2:GAUGE:10:0:U \	 # DataSource: over max of 10sec, "0" minimum and unknown max value as valid data
    # DS:Rpm3:GAUGE:10:0:U \	 # DataSource: over max of 10sec, "0" minimum and unknown max value as valid data
    # RRA:AVERAGE:0.5:1:10 \	 # Archive: Average over 1   measurement  (10 sec),  10 values should be stroed
    # RRA:AVERAGE:0.5:6:60 \	 # Archive: Average over 6   measurements (1 min),   60 values should be stroed
    # RRA:AVERAGE:0.5:24:240 \   # Archive: Average over 24  measurements (4 min),  240 values should be stroed
    # RRA:AVERAGE:0.5:288:2880 \ # Archive: Average over 288 measurements (42 min),2880 values should be stroed
    # RRA:MAX:0.5:1:10 \	 # Archive: MAX     over 1   measurements (10 sec),  10 values should be stroed
    # RRA:MAX:0.5:6:60 \	 # Archive: MAX     over 6   measurements (1 min),   60 values should be stroed
    # RRA:MAX:0.5:24:240 \	 # Archive: MAX     over 24  measurements (4 min),  240 values should be stroed
    # RRA:MAX:0.5:288:2880 \	 # Archive: MAX     over 288 measurements (42 min),2880 values should be stroed
    # RRA:LAST:0.5:1:10 \	 # Archive: Last    over 1   measurement  (10 sec),  10 values should be stored
    # RRA:LAST:0.5:6:60 \	 # Archive: MAX     over 6   measurements (1 min),   60 values should be stroed
    # RRA:LAST:0.5:24:240 \	 # Archive: MAX     over 24  measurements (4 min),  240 values should be stroed
    # RRA:LAST:0.5:288:2880 \	 # Archive: MAX     over 288 measurements (42 min),2880 values should be stroed

# 720 days	=720*288	=360 steps * 576 pixel columns
#  60 days	= 60*288	= 30 steps * 576 pixel columns
#  14 days	= 14*288	= 7 steps * 576 pixel columns
#   2 days	= 2*288	        = 1 steps * 576 pixel columns
#
    #system( "$rrdtool", "create", 
    RRDs::create (
            "$rrd_file",
    	    "--step", "60",
            'DS:cpu00:GAUGE:600:0:U',
            'DS:cpu01:GAUGE:600:0:U',
            'DS:cpu10:GAUGE:600:0:U',
            'DS:cpu11:GAUGE:600:0:U',
	    'DS:twa000:GAUGE:600:0:U',
	    'DS:twa001:GAUGE:600:0:U',
	    'DS:twa002:GAUGE:600:0:U',
	    'DS:twa003:GAUGE:600:0:U',
    	    'RRA:AVERAGE:0.5:1:576',
    	    'RRA:AVERAGE:0.5:7:576',
    	    'RRA:AVERAGE:0.5:30:576',
    	    'RRA:AVERAGE:0.5:360:576',
    	    'RRA:MAX:0.5:1:576',
    	    'RRA:MAX:0.5:7:576',
    	    'RRA:MAX:0.5:30:576',
    	    'RRA:MAX:0.5:360:576',
    	    'RRA:LAST:0.5:1:576',
    	    'RRA:LAST:0.5:7:576',
    	    'RRA:LAST:0.5:30:576',
    	    'RRA:LAST:0.5:360:576' 
	   );
        my $rrderror = RRDs::error;
        die "Problem while creating rrd: $rrderror\n" if ($rrderror);
}
#-----------------------------------------------------------------
sub record_fanspeed{
    my $stats_ref = shift @_;
    my $rrd_file=shift ;
    if ( $debug eq 1 ){ 
        print "Adding Data to rrd:\n"; 
        for my $key ( sort ( keys(%$stats_ref) ) ){
            print "\t$key:\t$$stats_ref{$key}\n";
        }
    }
    #system ( "$rrdtool","update",
    RRDs::update (
	     "$rrd_file",
	     "--template",
	     "cpu00:cpu01:cpu10:cpu11:twa000:twa001:twa002:twa003",
	     "N:$$stats_ref{cpu00}:$$stats_ref{cpu01}:$$stats_ref{cpu10}:$$stats_ref{cpu11}:$$stats_ref{twa000}:$$stats_ref{twa001}:$$stats_ref{twa002}:$$stats_ref{twa003}",	 
           );	
}
#-----------------------------------------------------------------
sub graph_fanspeed {

 # Create hash based for the time intervals we are interested in
 my %graph_perioud=(  "2hr"  => -1*60*60*2,
	              "12hr" => -1*60*60*12,
	              "1wk"   => -1440*24*7,
		      "1mo"  => -1440*24*7*4,
		      "1yr"   => -1440*24*365,
		    );

 for my $key (keys %graph_perioud){
   print "$key\t$graph_perioud{$key}\n";

   my $image_file_name_cpu="$rrd_dir/cpu_temp_${key}.png";

   if ( $debug eq 1 ){  print "Draw $key CPU Temp: $image_file_name_cpu\n"; }
   RRDs::graph (
            "$image_file_name_cpu",
   	    "--imgformat=PNG",
   	    "--start=$graph_perioud{$key}",
   	    "-c", "BACK#343435", 
            "-c", "FONT#ffffff", 
            "-c", "CANVAS#605f60",
   	    "--title=CPU Temp for $key",
   	    "--height=$graph_height", "--width=$graph_width", 
   	    "--vertical-label=Temp (°C)",
   	    "--step", "10",
   	    "DEF:cpu00a=$rrd_file:cpu00:AVERAGE", 
   	    "DEF:cpu00m=$rrd_file:cpu00:MAX",
   	    "DEF:cpu00l=$rrd_file:cpu00:LAST",
   	    "DEF:cpu01a=$rrd_file:cpu01:AVERAGE", 
   	    "DEF:cpu01m=$rrd_file:cpu01:MAX",
   	    "DEF:cpu01l=$rrd_file:cpu01:LAST",
   	    "DEF:cpu10a=$rrd_file:cpu10:AVERAGE", 
   	    "DEF:cpu10m=$rrd_file:cpu10:MAX",
   	    "DEF:cpu10l=$rrd_file:cpu10:LAST",
   	    "DEF:cpu11a=$rrd_file:cpu11:AVERAGE", 
   	    "DEF:cpu11m=$rrd_file:cpu11:MAX",
   	    "DEF:cpu11l=$rrd_file:cpu11:LAST",
            "LINE1:cpu00l#e106fb:cpu00\\:", 
   	      "GPRINT:cpu00a:AVERAGE:Ave\%6.2lf°C", 
   	      "GPRINT:cpu00m:MAX:Max\%6.2lf°C",
   	      "GPRINT:cpu00l:LAST:Last\%6.2lf°C",
   	      "COMMENT:\\n",  
   	    "LINE1:cpu01l#c001ff:cpu01\\:", 
   	      "GPRINT:cpu01a:AVERAGE:Ave\%6.2lf°C", 
   	      "GPRINT:cpu01m:MAX:Max\%6.2lf°C",
   	      "GPRINT:cpu01l:LAST:Last\%6.2lf°C",
   	      "COMMENT:\\n",  
   	    "LINE1:cpu10l#6701ff:cpu10\\:", 
   	      "GPRINT:cpu10a:AVERAGE:Ave\%6.2lf°C", 
   	      "GPRINT:cpu10m:MAX:Max\%6.2lf°C",
   	      "GPRINT:cpu10l:LAST:Last\%6.2lf°C",
   	      "COMMENT:\\n",  
   	    "LINE1:cpu11l#01baff:cpu11\\:", 
   	      "GPRINT:cpu11a:AVERAGE:Ave\%6.2lf°C", 
   	      "GPRINT:cpu11m:MAX:Max\%6.2lf°C",
   	      "GPRINT:cpu11l:LAST:Last\%6.2lf°C",
   	      "COMMENT:\\n",  
   );
   my $image_file_name_disk="$rrd_dir/temp_${key}.png";

   if ( $debug eq 1 ){  print "Draw 2 Hour Temp: $image_file_name_disk\n"; }
   RRDs::graph (
            "$image_file_name_disk",
   	    "--imgformat=PNG",
   	    "--start=$graph_perioud{$key}",
   	    "-c", "BACK#343435", 
            "-c", "FONT#ffffff", 
            "-c", "CANVAS#605f60",
   	    "--title=DISK Temp for $key",
   	    "--height=$graph_height", "--width=$graph_width", 
   	    "--vertical-label=Temp (°C)",
   	    "--step", "10",
   	    "DEF:twa000a=$rrd_file:twa000:AVERAGE", 
   	    "DEF:twa000m=$rrd_file:twa000:MAX",
   	    "DEF:twa000l=$rrd_file:twa000:LAST",
   	    "DEF:twa001a=$rrd_file:twa001:AVERAGE", 
   	    "DEF:twa001m=$rrd_file:twa001:MAX",
   	    "DEF:twa001l=$rrd_file:twa001:LAST", 
   	    "DEF:twa002a=$rrd_file:twa002:AVERAGE", 
   	    "DEF:twa002m=$rrd_file:twa002:MAX",
   	    "DEF:twa002l=$rrd_file:twa002:LAST", 
   	    "DEF:twa003a=$rrd_file:twa003:AVERAGE", 
   	    "DEF:twa003m=$rrd_file:twa003:MAX",
   	    "DEF:twa003l=$rrd_file:twa003:LAST", 
   	    "LINE1:twa000l#00ff80:twa000\\: ", 
   	      "GPRINT:twa000a:AVERAGE:Ave\%6.2lf°C", 
   	      "GPRINT:twa000m:MAX:Max\%6.2lf°C",
   	      "GPRINT:twa000l:LAST:Last\%6.2lf°C",
   	      "COMMENT:\\n",  
   	    "LINE1:twa001l#00ffc0:twa001\\: ", 
   	      "GPRINT:twa001a:AVERAGE:Ave\%6.2lf°C", 
   	      "GPRINT:twa001m:MAX:Max\%6.2lf°C",
   	      "GPRINT:twa001l:LAST:Last\%6.2lf°C",
   	      "COMMENT:\\n",  
   	    "LINE1:twa002l#00fff0:twa002\\: ", 
   	      "GPRINT:twa002a:AVERAGE:Ave\%6.2lf°C", 
   	      "GPRINT:twa002m:MAX:Max\%6.2lf°C",
   	      "GPRINT:twa002l:LAST:Last\%6.2lf°C",
   	      "COMMENT:\\n",  
   	    "LINE1:twa003l#00eaff:twa003\\: ", 
   	      "GPRINT:twa003a:AVERAGE:Ave\%6.2lf°C", 
   	      "GPRINT:twa003m:MAX:Max\%6.2lf°C",
   	      "GPRINT:twa003l:LAST:Last\%6.2lf°C",
   	      "COMMENT:\\n",  
   );
 }
}
#-----------------------------------------------------------------
sub update_fanspeed {
    my $NewSpeed=shift;
    open ( FANSPEED, ">>$ProcFile") || die "Cannot read fanspeed file: $?\n";
    print FANSPEED "$NewSpeed";
    close ( FANSPEED ) || die "Cannot close fanspeed file: $?\n";
    return;
}    
#-----------------------------------------------------------------
sub new_fanspeed {
    my $stats_ref = $_;
    #
    # If temp is over 42, increment fan speed.
    #
    if (  "$stats_ref->{Case1}" > $TargetTmp_upper ){ unless( $Speed1 eq 255){ ++$Speed1 ; } }    
    #
    # If temp is under 42, decrement fan speed.
    #
    if (  "$stats_ref->{Case1}"< $TargetTmp_lower ){ unless( $Speed1 eq 0 ){ --$Speed1 ; } }
    #
    # Return the new speed
    #
    return ( $Speed1 );
}
#-----------------------------------------------------------------
sub get_file_fanspeed {
    open ( FANSPEED, "<$ProcFile") || die "Cannot read fanspeed file: $?\n";
    chomp ( my $Speed1=<FANSPEED> );
    print "Speed1=$Speed1";
    close ( FANSPEED ) || die "Cannot close fanspeed file: $?\n";
    return ( $Speed1 );
}
#-----------------------------------------------------------------
sub get_i2c {
    my $stats_ref = shift @_;
    my $Case1;
    my $Case2;
    my $Case3;
    my $rpm1;
    my $rpm2;
    my $rpm3;
    my $cpu00;
    my $cpu01;
    my $cpu10;
    my $cpu11;
    my $Start;

    if ( $debug eq "1" ){  print "Parsing lm_sensors output\n"; }

   
    open ( SENSORS, "$sensors |") || die "Cannot run sensors\n";
    my $input;
    {
    	local $/;
    	$input = <SENSORS>;
    }
#
# Example Data
#
# k8temp-pci-00c3
# Adapter: PCI adapter
# Core0 Temp:
#         +44°C
# Core1 Temp:
#         +37°C
#
# k8temp-pci-00cb
# Adapter: PCI adapter
# Core0 Temp:
#           +46°C
# Core1 Temp:
#           +38°C
#
           #while( $input =~ /k8temp-pci-00c3(.*?)(\d+).C(.*?)(\d+).C$/smg ){
           while( $input =~ /k8temp-pci-00c3(.*?)(\d+).C(.*?)(\d+).C$/smg ){
               $cpu00=$2;
               $cpu01=$4;
               if ( $debug eq "1" ){  print "\tCPU00:\t$cpu00\n\tCPU01:\t$cpu01\n"; }
           }
           while( $input =~ /k8temp-pci-00cb(.*?)(\d+).C(.*?)(\d+).C$/smg ){
               $cpu10=$2;
               $cpu11=$4;
               if ( $debug eq "1" ){  print "\tCPU10:\t$cpu10\n\tCPU11:\t$cpu11\n"; }
           }
    # Should never get here.
    close ( SENSORS );
    
    if ( 1 ){
	$stats_ref->{cpu00}  = "$cpu00";
	$stats_ref->{cpu01}  = "$cpu01";
	$stats_ref->{cpu10}  = "$cpu10";
	$stats_ref->{cpu11}  = "$cpu11";

        return ( 1 ) ;
    } else {
        exit 1;
    }  
}
#-----------------------------------------------------------------
sub hd_temp {
    if ( $debug eq 1 ){ print "Entering hd_temp on twa0\n"; }
    #
    # 2 drives on /dev/twa1
    #
    for my $drive ( 0..1 ){
        $drive=sprintf ("%02d", $drive); # Format drive number, padding the tens place
        open( HDTEMP, "$smartctl -A --device=3ware,$drive  /dev/twa1|" )|| die "Cannot run smartctl:\t$!\n";
        while (<HDTEMP>){
            if ( $_  =~ m{
                            194                 # starts with 194
			    \s+                 # spaces
			    Temperature_Celsius # the word
			    \s+                 # spaces
			    0x\d+               # Some hex number 0x0022
			    \s+                 # spaces
			    (\d+)               # the temp we want
                            \s+                 # space
			    .*                  # Other stuff
			    \n                  # new line
                        }xig              # allow comments, case insensetive, global
             ) {
                 #
                 # Debug: Print the captured value
                 #	       
	         if ( $debug eq 1 ){ print "\ttwa1$drive:\t$1\n";  }
	         $stats{ "twa1$drive" }  = "$1";
             }
        }
        close(HDTEMP) ;
    }
    #
    # 16 drives on /dev/twa0
    #
    if ( $debug eq 1 ){ print "Entering hd_temp on twa1\n"; }
    for my $drive ( 00..15 ){
        $drive=sprintf ("%02d", $drive);
 	open( HDTEMP, "$smartctl -A  --device=3ware,$drive /dev/twa0 |" )|| die "Cannot run smartctl:\t$!\n";
        while (<HDTEMP>){
            if ( $_  =~ m{
                            194                 # starts with 194
			    \s+                 # spaces
			    Temperature_Celsius # the word
			    \s+                 # spaces
			    0x\d+               # Some hex number 0x0022
			    \s+                 # spaces
			    (\d+)               # the temp we want
                            \s+                 # space
			    .*                  # Other stuff
			    \n                  # new line
                        }xig              # allow comments, case insensetive, global
             ) {
                 #
                 # Debug: Print the captured value
                 #	       
	         if ( $debug eq 1 ){ print "\ttwa0$drive:\t$1\n";  }
	         $stats{ "twa0$drive" }  = "$1";       
             }
        }
        close(HDTEMP);
    }
    return( 1 );
}
#-----------------------------------------------------------------
sub make_index {
    my $html_file=qq{<html>
<link rel="icon" href="/favicon.ico" type="image/x-icon" >
<link rel="shortcut icon" href="/favicon.ico" type="image/x-icon" >
<meta http-equiv="refresh" content="120;URL=./">
<head>
</head>

<body bgcolor="black" Text="Yellow" >
<table border="1" >
<tr>
  <tdcolspan=2><a href="/scripts/perl/sensors.rrd.pl">Download this script</a></td>
</tr><tr>
  <tdcolspan=2><a href="http://users.erols.com/chare/elec.htm">CPU Temp Specs</a></td>
</tr><tr>
  <td colspan=2>Page Reloads every 2min. (LAST UPDATE:$EventDate)</td>
</tr><tr>
  <td><img src="temp_2hr.png" alt="2 hour hd temp">  </td>
  <td valign=top><img src="cpu_temp_2hr.png"  alt="2 hour cpu temp"> </td>
</tr><tr>
  <td><img src="temp_12hr.png" alt="12 hour temp"></td>
  <td valign=top><img src="cpu_temp_12hr.png" alt="12 hour fan"></td>
</tr><tr>
  <td><img src="temp_1wk.png" alt="1 week temp"></td>
  <td valign=top><img src="cpu_temp_1wk.png" alt="1 week fan"></td>
</tr><tr>
  <td><img src="temp_1mo.png" alt="1 month temp"></td>
  <td valign=top><img src="cpu_temp_1mo.png" alt="1 week fan"></td>
</tr><tr>
  <td><img src="temp_1yr.png" alt="1 year temp"></td>
  <td valign=top><img src="cpu_temp_1yr.png" alt="1 week fan"></td>
</tr>
</table>
</body>
    };
    
    open ( HTML, ">$index_file") || die "Could not open file:\t$?\n";
    print HTML "$html_file\n";
    close (HTML);

    return ( 1 );
}

