#!/s/perl/bin/perl -w

###############################################################################
#
#  1wire-make-swf.pl 
#
#  get x, y, t data for the last t minutes, make swf form the data
#
#  takes minutes, filename
#
################################################################################


################################################################################
# Tim Czerwonka, timc@cs.wisc.edu
# $Id: 1wire-make-swf.pl,v 1.8 2008/11/21 17:15:18 timc Exp $
#
# $Log: 1wire-make-swf.pl,v $
# Revision 1.8  2008/11/21 17:15:18  timc
# now takes a time interval
#
# Revision 1.7  2008/02/22 16:47:17  timc
# only look at sensors at the 7' level for now
#
# Revision 1.6  2008/02/18 16:40:26  timc
# forced aspect ratio in gnuplot graph to better fit machine room
#
# Revision 1.5  2007/12/12 17:15:29  timc
# use working version of gnuplot
#
# Revision 1.4  2007/11/26 22:44:57  timc
# to work with cent5
#
# Revision 1.3  2007/11/26 22:37:53  timc
# using default version of gnuplot
#
# Revision 1.2  2007/11/26 22:18:35  timc
# takes filename and other minor tweaks
#
# Revision 1.1  2007/11/26 21:20:16  timc
# Initial revision
#
################################################################################


use Data::Dumper;
use CSL::Pg;
use CSL::DBs;
use DBI;
my $dbh = DBI->connect($CSL::DBs::csdb) or die $DBI::errstr; 
$dbh->do("set search_path to sensornet");

use lib "/s/lab/src/1wire/ming/lib/site_perl/5.8.6/i686-linux-64int";

use SWF qw(:ALL);
SWF::setScale(1);
SWF::setVersion(6);




################################################################################
# functions
################################################################################

#this is such bullshit
sub parse_the_expletive_deleted_date{
    local($crap) = @_;
    my @parsedate = localtime($crap);
    ($sec,$min,$hour,$mday,$mon,$year) = @parsedate;
    $year += 1900;
    $mon +=1;
    return "$year-$mon-$mday $hour:$min:$sec";
}



# get_sensor_location -- return xyz location of specified device id
sub get_xyt_sensor_data_time{
    local ($starttime, $stoptime) = @_;
        
    my @retval;

    my $start=parse_the_expletive_deleted_date($starttime);
    my $stop=parse_the_expletive_deleted_date($stoptime);

    my $query = $dbh->prepare("SELECT id, x, y, value
                               FROM data
                                  WHERE time >= ? 
                                  AND time < ?
				  AND z=7
                               ORDER BY time");

    $query->execute($start, $stop);
    $data = $query->fetchrow_hashref;
    while ($data->{value}) {
	push(@retval,$data->{x});
	push(@retval,$data->{y});
	push(@retval,($data->{value}) * 1.8 + 32);
# 	print $data->{x} . " " . $data->{y} . " " . (($data->{value}) * 1.8 + 32);
# 	print "\n";
 	$data = $query->fetchrow_hashref;
    }
    return @retval ;
}



# get_sensor_list -- return an array of all available sensors
sub get_sensor_list {
    my @sensorlist;

    my $query = $dbh->prepare("SELECT id
                               FROM sensors");

    $query->execute();
    $data = $query->fetchrow_hashref;
    while ($data->{id}) {
	push(@sensorlist, $data->{id});
	$data = $query->fetchrow_hashref;
    }
    return @sensorlist;
}



# make_graphic -- make the graphic image
sub make_graphic{
    local ($filename, $image_file, $time) = @_;
    #make a human-readable title for this
    my $time=parse_the_expletive_deleted_date($time);
    my $gnuplot_commands = "set dgrid3d 60\, 25;
			    set size ratio 0.417;
                            set cbrange [45:100];
                            set view 0\,0;
                            unset surface;
                            set pm3d at b;
                            set contour base;
                            set ticslevel 0.8;
                            set isosample 40\,40;
                            set pm3d map;
                            set palette rgbformula 22\,13\,-31;
                            set terminal jpeg;
                            set output '$image_file';
                            set title '$time';
                            splot '$filename' u 1:2:3 with lines";


    open (GP, "|/s/gnuplot-4.2.2/bin/gnuplot -persist") or die "gnuplot not found";
    # force buffer to flush after each write
    use FileHandle;
    GP->autoflush(1);
    print GP $gnuplot_commands;
    close GP;
    return 0;

}


################################################################################
# main 
################################################################################
my $tmp;
my $corner_data="0 0 70\n0 25 70\n60 0 70\n60 25 70\n";



#check that we can create a file in /tmp for writing the numbers out
if (!$ENV{'TEMP'}) {
    $tmp = "/tmp";
} else {
    $tmp = $ENV{'TEMP'};
}




#oh, this is ugly
while( @ARGV ) {
    $_ = shift;
    $seconds_back = $_;
    $_ = shift;
    $step = $_;
    $_ = shift;
    $output_file = $_;
}


# if called with no arguments, select only the last five minutes
if (!$seconds_back) {
    $seconds_back = 300;
}

# similarly, do a five-minute step (300 seconds) if one isn't specified
if (!$step) {
    $step = 300;
}



### set up to create SWF from individual frames
my $m = new SWF::Movie();




### loop forward on a rolling time horizon in five minute increments

#set now_time to current time
$now_time = time(); #seconds since epoch

$start_time = $now_time - $seconds_back;

#while start_time < now_time  --- that is , while it's still in the past, not future

while ($start_time < $now_time) {
    #  stop_time = start_time + five minutes
    $stop_time = $start_time + $step;
    #get the data for the timerange
    my @datablock = get_xyt_sensor_data_time($start_time, $stop_time);
    #  start_time = stop_time
    $start_time = $stop_time;



    #now generate a graph
    #open a file for writing
    my $now = time();
    my $the_numbers="$tmp\/1wire.$$";    
    my $image_file="$tmp\/1wire-image-$$.jpg";    
    open(LOGFILE, ">>$the_numbers") || warn "Can't open logfile $the_numbers: $!";

    while(@datablock) {
	print LOGFILE shift(@datablock);
	print LOGFILE " ";
	print LOGFILE shift(@datablock);
	print LOGFILE " ";
	print LOGFILE shift(@datablock);
	print LOGFILE "\n";
    }
    print LOGFILE $corner_data;
    close(LOGFILE);

    #make the graphic
    make_graphic($the_numbers, $image_file, $start_time);

    #handle the SWF image addition
    #this should be the same file over and over someday
    my $bitmap = new SWF::Bitmap($image_file);
    #create fill, required to place bitmap
    my $s = new SWF::Shape();
    my $f = $s->addFill($bitmap);
    $s->setRightFill($f);
    my $bitmap_width = $bitmap->getWidth();
    my $bitmap_height = $bitmap->getHeight();
    $s->drawLine($bitmap_width, 0);
    $s->drawLine(0,$bitmap_height);
    $s->drawLine(-$bitmap_width,0);
    $s->drawLine(0,-$bitmap_height);
    #$m is the movie, constructed prior to this while loop
    $m->setDimension($bitmap_width, $bitmap_height);
    #add the bitmap object to the movie
    $m->add($s);


    #go to the next frame
    $m->nextFrame();

    #remove the files
    unlink($the_numbers);
    unlink($image_file);
}




$m->save($output_file);


exit 0;

