Tuesday, 6 November 2012

Logging Heatmiser Data

After getting my Heatmiser thermostat, I wasn't content with just using the (rather 2000's style) web GUI, I wanted a way to interact with the device directly, and at the time there was no Android app for Heatmiser.

With the help of viewing lots of source code from the Heatmiser web GUI and traces from wireshark, I was able to identify the basics of how the forms on the web GUI work.  I know there is the iPhone interface, but it's a pretty evil protocol for what is a very small basic set of functions I needed, and I decided that interacting with the web GUI was far quicker and easier.

The code was/is less than optimal or pretty, but it works (just about).

The code to log the current and set temperature along with the heating status is Perl based, and written to run in a unix environment.

#!/usr/bin/perl
use DBI;

$dbh = DBI->connect('DBI:mysql:Monitoring', '<username>', '<password>') || die "Could not connect to database: $DBI::errstr";

@userinput = `wget -q -O- http://<heatmiser_IP>/right.htm`;

foreach (@userinput) {
$line = $_;
if ( ( $cur,$set,$state ) = $line =~ m/.*Actual.*'5'>(\d{1,}.*?)&nbsp.*'4'>(\d{1,}.*?)&nbsp.*((ON|OFF))/ )
{
$date = `date "+%Y-%m-%d %H:%M"`;
if ( $state =~ /OFF/ )
{
$state = "0";
}
elsif ( $state =~ /ON/ )
{
$state = "1";
}
chomp($date);
$date = "$date:00"; //Fix the date to be 00 seconds
$dbh->do("INSERT INTO `heating` SET date=\'$date\',actualtemp=$cur,settemp=$set,onoff=$state");
}
}


And the PHP to make the Google charts work:

<?php
$DB_NAME 
'Monitoring';$DB_HOST '<HOST>';$DB_USER '<USERNAME>';$DB_PASS '<PASSWORD>';
$mysqli = new mysqli($DB_HOST$DB_USER$DB_PASS$DB_NAME);
if (
mysqli_connect_errno()) {
    
printf("Connect failed: %s\n"mysqli_connect_error());
    exit();
}
if(!isset(
$_REQUEST['duration']))
{
    
$duration 1;
}
else{
    
$duration $_REQUEST['duration'];
}
$date date("Y-m-d H:i:s",time()-($duration*86400));$query "SELECT * FROM `heating` WHERE `date` > '$date'";$result $mysqli->query($query) or die($mysqli->error.__LINE__);?>
<html>
  <head>
    <script type="text/javascript" src="https://www.google.com/jsapi"></script>
    <script type="text/javascript">
      google.load("visualization", "1", {packages:["corechart"]});
      google.setOnLoadCallback(drawChart);
      function drawChart() {
        var data = new google.visualization.DataTable();
        data.addColumn('string', 'Date');
        data.addColumn('number', 'Actual Temp');
        data.addColumn('number', 'Set Temp');
        data.addColumn('number', 'State (1=on, 0=off)');
        data.addRows([
    <?phpwhile($row $result->fetch_assoc()) {
    echo 
"['";
    echo 
$row['date'];
    echo 
"', ";
    echo 
$row['actualtemp'];
    echo 
", ";
    echo 
$row['settemp'];
    echo 
", ";
    echo 
$row['onoff'];
    echo 
"],\n";
    
$date $row['date'];
    
$actualtemp $row['actualtemp'];
    
$settemp $row['settemp'];
    
$onoff =$row['onoff'];
    }
        echo 
"['";
        echo 
$date;
        echo 
"', ";
        echo 
$actualtemp;
        echo 
", ";
        echo 
$settemp;
        echo 
", ";
        echo 
$onoff;
        echo 
"]\n";

    
mysqli_close($mysqli);?>        ]);

        var options = {
        title: 'Temperature History',
        vAxis: {title: "Temperature"},
        hAxis: {title: "Date / Time"},
        };

        var chart = new google.visualization.AreaChart(document.getElementById('chart_div'));
        chart.draw(data, options);
      }
    </script>
  </head>
  <body>

    <div id="chart_div" style="width: 1000; height: 640;"></div>
  </body>
</html>

-------------

This produces a chart such as this, which shows a 24hour period.  To display 2 days, pass "?duration=2" to the code, or for 12 hours, pass "?duration=0.5", if you want to display any other values, it is just a factor of 1 = where 1 = 24hours, so 1hour = 0.0417.


No comments:

Post a Comment