#!/usr/bin/perl
# -*- Perl -*-
#
# DigiTemp v2.1 gnuplot script
# Modified by Brian C. Lane <bcl@brianlane.com> www.brianlane.com
# 
# Modified plot script from Russell Nelson <nelson@crynwr.com>
# for use with the GD module for Perl
#
# The GD module can be found at:
#   http://www.perl.com/CPAN-local//modules/by-module/GD/
#
# More mods to add maximum and minimum temp display for each day
# NOTE: You will need to change the commands at the bottom that tell
# where to store and move the final .gif file to.
#
use GD;

# Transform the temperature into graph coordinates. Convert to Farenheit
# I already have fahrenheight data, so no conversion is needed.
sub ytransform {
    $temp = shift;
#    $temp = $temp * 9 / 5 + 32;
    return int(250 - 2*$temp);
}

# You will need to customize these values for your setup
$height = 350;
$hmargin = 40;
$middlex = 300;
# display them all!
$dx=2.0/1.0;
# # of temperatures per sample (number of sensors)
$sensors = 3;
$samples_per_hour = 2;
# 5 Days, 24 hours a day, 2 samples per hour
$samples = 5*24* $samples_per_hour;
$width = $hmargin + $samples*$dx + $hmargin;

# print PLOT "create plot $width $height\n";
$im = new GD::Image( $width, $height );

# Allocate a bunch of colors
($white,$black,$red,$green,$orange,$lightgreen,$blue,$skyblue) = 
    (
     $im->colorAllocate(255, 255, 255),
     $im->colorAllocate(0, 0, 0),
     $im->colorAllocate(255, 0, 0),
     $im->colorAllocate(0,255,0),
     $im->colorAllocate(255,0,255),
     $im->colorAllocate(0,128,0),
     $im->colorAllocate(0,0,255),
     $im->colorAllocate(100,100,255)
     );

# Grayscale -- Not currently used. I'll skip for now
#for ($i=0; $i<128; $i++) {
#    print PLOT "colorallocate plot gray$i ".$i*2 ." ".$i*2 ." ".$i*2 ."\n";
#}

#sub dogray {
#    ($light) = @_;
#
#    if ($light < -70) {
#	$gray = int(0.5 + 32 * ($light - -92) / (-70 - -92));
#    } elsif ($light < 265) {
#	$gray = int(32.5 + 32 * ($light - -70) / (265 - -70));
#    } else {
#	$gray = int(64.5 + 64 * ($light - 265) / (290 - 265));
#    }
#    $gray = 0 if ($gray < 0);
#    $gray = 127 if ($gray > 127);
#    print PLOT "filledrectangle plot ";
#    print PLOT "$x 20  ";
#    print PLOT $x+$dx." ".($height-20)."  gray$gray\n";
#}



# Draw a Horizontal line at a temperature point
sub hline {
    ($y,$color) = @_;
    $color = $skyblue unless $color;
    $yname = $y;
    $y = &ytransform($y);
    $ychar = $y-6;
    $numleft = 10;
    $lineleft = 26;
    $lineright = $width - 24;
    $numright = $width - 20;
#    print PLOT "string plot gdFont6x13 $numleft $ychar \"$yname\" $color\n";
    $im->string(gdSmallFont,$numleft,$ychar,$yname,$color);
#    print PLOT "line plot $lineleft $y $lineright $y $color\n";
    $im->line($lineleft,$y,$lineright,$y,$color);
#    print PLOT "string plot gdFont6x13 $numright $ychar \"$yname\" $color\n";
    $im->string(gdSmallFont,$numright,$ychar,$yname,$color);
}

# Draw the temperature reference lines
#&hline(-20);
&hline(0 );
&hline(20 );
&hline(32, $lightgreen );
&hline(40 );
&hline(60 );
&hline(80 );
&hline(100 );

sub xtransform {
    return $hmargin + $dx * shift;
}

# Draw a vertical line
sub vline {
    ($x,$label,$color) = @_;
    $color = $skyblue unless $color;
    $x = &xtransform($x);
    $linetop = &ytransform(100);
    $linebot = &ytransform(-20);
    $ychar = &ytransform(107);
#    print PLOT "string plot gdFont6x13 $x $ychar \"$label\" $color\n";
    $im->string(gdSmallFont,$x-5,$ychar,$label,$color);
#    print PLOT "line plot $x $linetop $x $linebot $color\n";
    $im->line($x,$linetop,$x,$linebot,$color);
}


# See if the min or max data for the current day should be changed
# This function has been tested and works
sub minmax {
  ($sample,$temp,$sensor) = @_;

  $day = int($sample / (24 * $samples_per_hour ) );
 
  if( $temp > $max_temp[$day][$sensor] )
  {
#print "oldmax[$day][$sensor] =  $max_temp[$day][$sensor]\n";
      $max_temp[$day][$sensor] = $temp;
#print "newmax[$day][$sensor] =  $max_temp[$day][$sensor]\n";
  }

  if( $temp < $min_temp[$day][$sensor] )
  {
#print "oldmin[$day][$sensor] =  $min_temp[$day][$sensor]\n";
      $min_temp[$day][$sensor] = $temp;
#print "newmin[$day][$sensor] =  $min_temp[$day][$sensor]\n";
  }
}


# --------------------------------[ MAIN CODE ]----------------------------

# Draw the vertical day lines
&vline(0*24*$samples_per_hour," -5d");
&vline(1*24*$samples_per_hour," -4d");
&vline(2*24*$samples_per_hour," -3d");
&vline(3*24*$samples_per_hour," -2d");
&vline(4*24*$samples_per_hour," yesterday");
&vline(5*24*$samples_per_hour," now");

# Here we read in all the samples. I have 3 temps for every
# 30 minutes within the day.
$lines = $sensors * $samples;
open(DOTTEMP, "tail -$lines /gonzo/var/log/temperatures|");
@dottemp = <DOTTEMP>;
close(DOTTEMP);

# Now all the temps are in dottemp -- it might be better to read it line
# by line for bigger files?

# Initialize the initial variables - I should use a list for this
$x = $hmargin;
$_= $dottemp[0];
@_ = split( " ", $_ );
$lasty0 = &ytransform($_[8]);
$_= $dottemp[1];
@_ = split( " ", $_ );
$lasty1 = &ytransform($_[8]);
$_= $dottemp[2];
@_ = split( " ", $_ );
$lasty2 = &ytransform($_[8]);

# Init the max and min temps and their points on the graph
# Keep track of data for all of the last 5 days
for( 0 .. 4 )
{
  $day = $_;
  for( 0 .. 2 )
  {
    $max_temp[$day][$_] = -50;
    $min_temp[$day][$_] = 200;
  }
}

$sample = 0;

# Plot each of the datapoints.
foreach (@dottemp) {
  # Get the time and date, sensor number, temperature in c and f
  ($month,$day,$time,$d1,$sensor,$d1,$centigrade,$d1,$fahrenheight) = split(" ", $_ );

# Plot the next line for each sensor
# 0 - Harddrive #1 in gonzo
# 2 - Room Temperature
# 1 - Outside temperature
  if( $sensor eq '0' )
  {
    $color = $red;
    $y0 = &ytransform($fahrenheight);
    $im->line(int($x),$lasty0,int($x+$dx),$y0,$color);
    $lasty0 = $y0;

#   Run minmax for the current day and sensor
    &minmax( $sample, $fahrenheight, 0 );
  }
  if( $sensor eq '1' )
  {
    $color = $green;
    $y1 = &ytransform($fahrenheight);
    $im->line(int($x),$lasty1,int($x+$dx),$y1,$color);
    $lasty1 = $y1;

#   Run minmax for the current day and sensor
    &minmax( $sample, $fahrenheight, 1 );
  }
  if( $sensor eq '2' )
  {
    $color = $orange;
    $y2 = &ytransform($fahrenheight);
    $im->line(int($x),$lasty2,int($x+$dx),$y2,$color);
    $lasty2 = $y2;

#   Run minmax for the current day and sensor
    &minmax( $sample, $fahrenheight, 2 );

# Count the number of samples so we can figure out what day it is
    $sample++;

#   move to next position
    $x += $dx;
  }
}


# Print the Header for the Min/Max data for each day
for( 0 .. 4 )
{
  $im->string(gdSmallFont,3+&xtransform($_*24*$samples_per_hour),&ytransform(-1),"Min      Max",$black);
}


# Print the min and max temperatures

# Print the min/max for each day and sensor
for( 0 .. 4 )
{
$im->string(gdSmallFont,3+&xtransform($_*24*$samples_per_hour),&ytransform(-6),sprintf("%-6s   %s",$min_temp[$_][0],$max_temp[$_][0]),$red);
$im->string(gdSmallFont,3+&xtransform($_*24*$samples_per_hour),&ytransform(-11),sprintf("%-6s   %s",$min_temp[$_][1],$max_temp[$_][1]),$green);
$im->string(gdSmallFont,3+&xtransform($_*24*$samples_per_hour),&ytransform(-16),sprintf("%-6s   %s",$min_temp[$_][2],$max_temp[$_][2]),$orange);
}

# Add the Date and time
$date = `date "+Generated at %H:%M on %a, %b %d %Y"`;
chop $date;
$im->string(gdSmallFont,$middlex-5,&ytransform(-30),$date,$black);

# Advertise!
$im->string(gdSmallFont,$middlex-5,&ytransform(-35),"with DigiTemp - http://www.brianlane.com",$black);

# Print the Color Key
$im->string(gdSmallFont,$hmargin,&ytransform(-30),"Harddrive #1",$red);
$im->string(gdSmallFont,$hmargin,&ytransform(-35),"Room Temperature",$green);
$im->string(gdSmallFont,$hmargin,&ytransform(-40),"Outside Temperature",$orange);

# Output it to a .gif image file
open( PLOT, ">/tmp/tempplot.gif");
print PLOT $im->gif;
close(PLOT);

# copy the image to its final destination and make sure it is owned
# by the right person.
system "cp /tmp/tempplot.gif /home/nexus/.public_html/tempplot.gif";
system "chown nexus.users /home/nexus/.public_html/tempplot.gif";
system "chmod 0644 /home/nexus/.public_html/tempplot.gif";
