Venstar Runtimes Perl Program

The Venstar thermostat has a little-known API (application programming interface) that one can use to control and query it.  This Perl program gets the daily runtimes for the last week or so that the Venstar keeps and loads them into a file. It also reports runtimes to HCA.  This version was uploaded Jan 1, 2016.

# venstar-runtimes-2.pl
use LWP::UserAgent;
my $i;
($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time);
my $venheat1 = “-1”;
my $vencool1 = “0”;
my $vents = “0”;
my $outfile = “venruntimes.txt”;  #picked up by hca
my $outln = “”;
my $logfile = “venrunlog.txt”;  #keep a log
my $logln = “time:” . ($year-100) . sprintf(“%02d”,($mon+1)) . sprintf(“%02d”,($mday)) . “:”;
my $workfile = “venworkh1” . ($year-100) . “.txt”;
my $prevyearworkfile = “venworkh1” . ($year-101) . “.txt”;
my $workval = “-1”;
my $workctr = “0”;
# first open outfile to make sure at least disk is ok – if not die quickly
if (not (open OUTPUT, “> $outfile”))
{
die “Output file open error: $!”;
}
# print “workfile: $workfile\n”;
# print “pyworkfile: $prevyearworkfile\n”;
# open this year’s work file and read it into @workarray
if (not (open WORKIN, “$workfile”))
{
$outln = “venrstatus=2\n”;
print OUTPUT $outln;
close OUTPUT;
die “Work file open error: $!”;
}
my @workh1array = <WORKIN>;
close WORKIN;
# open last year’s work file and read it into @pyworkarray
if (not (open PYWORKIN, “$prevyearworkfile”))
{
$outln = “venrstatus=3\n”;
print OUTPUT $outln;
close OUTPUT;
die “Work file open error: $!”;
}
my @pyworkh1array = <PYWORKIN>;
close PYWORKIN;
#    print “wkarray: @workh1array\n”;
# create user agent and request for venstar
my $ua = new LWP::UserAgent;
my $req = new HTTP::Request ‘GET’,’http://192.168.2.148/query/runtimes’;
# fetch info from venstar
my $resp = $ua -> request($req);
# see if it ended ok
if ($resp->is_success)
{
my $message = $resp->decoded_content;
#    print “Received reply: $message\n”;
# remove quotes and brackets from venstar decoded response
$message =~ tr/”//d;
$message =~ tr/{//d;
$message =~ tr/}//d;
$message =~ tr/[//d;
$message =~ tr/]//d;
$message =  subs $message, 9;  # delete the first 9 chars
#    print “tempmsg1: $message\n”;
# create an array out of the remaining string using commas and colons
my @venrunarray = split /[,:]/, $message;
#    print “array: @venrunarray\n”;
my $arraycount = @venrunarray;
#    print “element count: $arraycount\n”;

open LOGPUT, “>> $logfile” or die “Output file open error: $!”;
print LOGPUT $logln;
print LOGPUT @venrunarray;
close LOGPUT;
my $setcount = $arraycount / 16;
if ($setcount != 1)   #if setcount = 1 must must be starting up, so ignore
# normally setcount should be 7.  We only care about the first 6 of these
# as the 7th one is for a partial day.  There are a total max of 56 elements
# and each one has 8 pairs of data, so we increment by 16 through the 112 items in the
#array.  They are in chrono order, the oldest day is the first set.
{
for ($i = 0; $i < ($setcount – 1); $i++)
{
my $epochseconds = $venrunarray[ ($i * 16) + 1 ];
($esec,$emin,$ehour,$emday,$emon,$eyear,$ewday,$eyday,$eisdst) = localtime($epochseconds);
#        print “eyday:” . $eyday . “\n”;
#        print “yday:” . $yday . “\n”;
#        print “eheat1val:” . $venrunarray[ ($i * 16) + 3 ] . “\n”;
# the last heat1 is the previous day’s, so keep overwriting
$venheat1 = $venrunarray[ ($i * 16) + 3 ] . “\n”;
if ($eyday lt $yday)  # this is the normal case, replace value in runarray
{
$workh1array[$eyday] = $venrunarray[ ($i * 16) + 3 ] . “\n”;
#            print “$eyday lt $yday\n”;
}
else  # must be at start of year
{
#            print “$eyday gt $yday\n”;
$pyworkh1array[$eyday] = $venrunarray[ ($i * 16) + 3 ] . “\n”;
}
}
#            print “wkarray: @workh1array\n”;
#             print “pywkarray: @pyworkh1array\n”;
open WORKIN, “>$workfile” or die “Work file open error: $!”;
foreach (@workh1array)
{
print WORKIN “$_”;
}
close WORKIN;
open PYWORKIN, “>$prevyearworkfile” or die ” PY Work file open error: $!”;
foreach (@pyworkh1array)
{
print PYWORKIN “$_”;
}
close PYWORKIN;
$thisline = “venrunts=” . ($eyear-100) . sprintf(“%02d”,($emon+1)) . sprintf(“%02d”,($emday)) . “\n”;
$outln = $outln . $thisline;
$thisline = “venheat1run=” . $venheat1;
$outln = $outln . $thisline;
$thisline = “vencool1run=” . $vencool1 .”\n”;
$outln = $outln . $thisline;
$thisline = “venrstatus=0\n”;
$outln = $outln . $thisline;
}
}    # end of good venstar response
else
{
#    print “HTTP POST error code: “, $resp->code, “\n”;
#    print “HTTP POST error message: “, $resp->message, “\n”;
$outln = “venrstatus=1\n”;
print OUTPUT $outln;
close OUTPUT;
$logln = “time:” . ($year-100) . sprintf(“%02d”,($mon+1)) . sprintf(“%02d”,($mday)) . “: venheat1run=-1” . “\n”;
open LOGPUT, “>> $logfile” or die “Output file open error: $!”;
print LOGPUT $logln;
close LOGPUT;
die “Venstar HTTP error”;
}
# finish writing hca file
print OUTPUT $outln;
close OUTPUT;
# either good or not, add to log file
$thisline = “venrunts=” . ($eyear-100) . sprintf(“%02d”,($emon+1)) . sprintf(“%02d”,($emday));
$outln = “”;
$outln = $outln . $thisline;
$thisline = “venheat1run=” . $venheat1;
$outln = $outln . $thisline;
$logln = “:” . $outln;
open LOGPUT, “>> $logfile” or die “Output file open error: $!”;
print LOGPUT $logln;
close LOGPUT;

Arduino, Venstar, Wemos, HCA, etc.