#!/usr/bin/perl
use CGI qw(Dump);
use POSIX qw(log10);

$LOG = "/home/hardl2/public_html/wattsup.txt";
$POWER_DATA_LOG = "/home/hardl2/public_html/wattsup_power_data.txt";
$POWER_DATA_BUFFER_SIZE = 60;

%WATTS_UP_DATA = (
  'id'  => "Machine ID",
  'rnc' => "Relay Status",
  'sr'  => "Send Rate",
  'w'   => "Watts",
  'v'   => "Volts",
  'a'   => "Amps",
  'wh'  => "Watt Hours",
  'wmx' => "Max Watts",
  'vmx' => "Max Volts",
  'amx' => "Max Amps",
  'wmi' => "Min Watts",
  'vmi' => "Min Volts",
  'ami' => "Min Amps",
  'pf'  => "Power Factor",
  'pcy' => "Power Cycle",
  'frq' => "Frequency",
  'va'  => "Volt Amps",
);

%WATTS_UP_SCALAR = (
  'id'  => 1.0,
  'rnc' => 1.0,
  'sr'  => 1.0,
  'w'   => 0.1,
  'v'   => 0.1,
  'a'   => 0.001,
  'wh'  => 0.1,
  'wmx' => 1.0,
  'vmx' => 1.0,
  'amx' => 1.0,
  'wmi' => 1.0,
  'vmi' => 1.0,
  'ami' => 1.0,
  'pf'  => 1.0,
  'pcy' => 1.0,
  'frq' => 0.1,
  'va'  => 1.0,
);


# -------------------------
# Main
# -------------------------
&parse_args;

exit(0);

# -------------------------
# Subroutines
# -------------------------

sub parse_args {
    my (@vars, $var, $num, $query, $name, $forum, $i, $forum_idx);


    # Extract POST or GET data (from $ENV{QUERY_STRING} or STDIN)
    $query = CGI::new();

    # In order to dump the entire query in a readable format, just
    # uncomment:
    $query_str = &Dump;

    @vars = $query->param;

    if (grep(/^newlog$/, @vars)) {
        open("LOG", ">$LOG") || die "Unable to open log file $LOG\n";
        # Create a header
        printf(LOG "JMP Epoch Time,Excel Epoch Time,");
        foreach $var (sort keys %WATTS_UP_DATA) {
            # Ignore some of the useless data
            next if ($var =~ /^(id|rnc|sr)$/);
            printf(LOG "$WATTS_UP_DATA{$var},");
        }
        printf LOG "\n";
        close LOG;
        print "Content-type: text/html\n\n";
        printf "New log started for '%s'\n", $query->param("newlog");
        exit(0);
    }
    else {
        open("LOG", ">>$LOG");
    }

    # Grab the power data log
    open (POWER_DATA_LOG, "<$POWER_DATA_LOG");
    @power_data = split(',', <POWER_DATA_LOG>);
    close POWER_DATA_LOG;

    # According to docs, here are the variables:
    # Machine ID     id      -- the unit serial number
    # Relay Status   rnc     -- Normally connected: '0', disconnected: '1'
    # Send Rate      sr      -- POST logging interval in seconds
    # Watts          w       -- Watts scaled by 10
    # Volts          v       -- Volts scaled by 10
    # Amps           a       -- Amperes scaled by 1000 (123 = 0.123 amps)
    # Watt Hours     wh
    # Max Watts      wmx
    # Max Volts      vmx
    # Max Amps       amx
    # Min Watts      wmi
    # Min Volts      vmi
    # Min Amps       ami
    # Power Factor   pf
    # Power Cycle    pcy
    # Frequency      frq     -- Line frequency scaled by 10
    # Volt Amps      va
     
    #printf(LOG "Input String: $ENV{QUERY_STRING}\n");

    # Note that most systems use an epoch as Jan 1, 1970.  
    # JMP uses Jan 1, 1904 (same as mac)
    # Time is reported in GMT, so need to subtract 8 hours
    # 
    # The NSPR epoch is midnight, Jan. 1, 1970 GMT.
    #
    # At midnight Jan. 1, 1970 GMT, the local time was
    #     midnight Jan. 1, 1970 + GMTDelta().
    #
    # Midnight Jan. 1, 1970 is 86400 * (365 * (1970 - 1904) + 17)
    #     = 2082844800 seconds since the Mac epoch.
    # (There were 17 leap years from 1904 to 1970.)
    #
    # So the NSPR epoch is 2082844800 + GMTDelta() seconds since
    # the Mac epoch.  Whew! :-)
    #
    # Excel calculates the dates as the number of days from 01/01/1900

    # JMP time in 1904 epoch time
    #
    printf(LOG "%s,", time + 2082816000);

    # excel time in 1900 epoch time, in units of days.  Remove compensation
    # for GMT
    #
    printf(LOG "%f,", (time + 2209132800) / 86400);

    foreach $var (sort keys %WATTS_UP_DATA) {
        # Ignore some of the useless data
        next if ($var =~ /^(id|rnc|sr)$/);

        if (!grep(/^$var$/,@vars)) {
            printf LOG ",";
        }
        else {
            $data = $query->param($var);
            $data = $data * $WATTS_UP_SCALAR{$var};

            # Save some storage space by limiting output to the precision of the wattsup
            $precision = log10(1/$WATTS_UP_SCALAR{$var});
            printf(LOG "%.${precision}f,", $data);

            if ($var eq "w") {
                push(@power_data, $data);
                if (scalar @power_data > $POWER_DATA_BUFFER_SIZE) {
                    shift @power_data;
                }
            }
        }
    }
    print LOG "\n";
    close LOG;

    open (POWER_DATA_LOG, ">$POWER_DATA_LOG");
    printf(POWER_DATA_LOG "%s", join(',', @power_data));
    close POWER_DATA_LOG;

    print "Content-type: text/html\n\n";
    # Set the refresh rate to 1sec if it isn't already there.
    if (eval($query->param("sr")) != 1) {
        print "[0!1]"
    }
    # else, just leave the power on!
    else {
        print "[0]"
    }
}