Saturday 18 October 2014

Creating RRD graphs for Raspbery Pi / DS18B20


So I wanted to move the TME sensor I bought in my previous post to the bitcoin mining room, to measure the temperature there.

I still needed to monitor the temp in the comms cupboard where I have 4 HP Microserver NASs, UPS, firewall, HP managed switch etc etc to make sure it isn't going to melt.

I saw this excellent article here that uses simple off the shelf electronics to accomplish this. Following this and buying the parts listed from Maplins and Pimori and ebay.

Maplins parts list:
Resistor pack (you never know when you might need more)

Pimori parts list:
Hook up wire (looked cool with all the colours)
ADA fruit pi - t cobbler
Adafruit raspberry pi perma proto
Raspberry Pi GPIO cable

Ebay parts list:
ds18b20t (waterproof version)
Total cost of parts incl Raspberry pi b model < £90

So I did some basic config following the article there and basically adding the following modules to /etc/modules
w1-gpio
w1_therm
then in /sys/bus/w1/devices/ should have the sensors with their individual serials there

phil@temp-comms /sys/bus/w1/devices $ ls -al
total 0
drwxr-xr-x 2 root root 0 Oct 18 00:13 .
drwxr-xr-x 4 root root 0 Oct 18 00:13 ..
lrwxrwxrwx 1 root root 0 Oct 18 00:13 28-0000062d26d0 -> ../../../devices/w1_bus_master1/28-0000062d26d0
lrwxrwxrwx 1 root root 0 Oct 18 00:13 28-0000062e10ae -> ../../../devices/w1_bus_master1/28-0000062e10ae
lrwxrwxrwx 1 root root 0 Oct 18 00:13 28-0000062e511a -> ../../../devices/w1_bus_master1/28-0000062e511a
lrwxrwxrwx 1 root root 0 Oct 18 00:13 w1_bus_master1 -> ../../../devices/w1_bus_master1
phil@temp-comms /sys/bus/w1/devices $ 



For each sensor there will be a 28-xxx directory, and under each directory 280000062xxxx there is is a file called w1_slave. Cat that and it'll have the temperature
phil@temp-comms /sys/bus/w1/devices/28-0000062d26d0 $ cat w1_slave
c7 01 4b 46 7f ff 09 10 01 : crc=01 YES
c7 01 4b 46 7f ff 09 10 01 t=28437
phil@temp-comms /sys/bus/w1/devices/28-0000062d26d0 $
t=temperature, but it's 1000 higher than it should, so just divide it by 1000 to get the temp in degrees celcius.



and then followed this article to use multiple temp sensors with the wiring like so




So what this article doesn't tell you is how to produce the graphs.
So obviously setting up cron with 1 minute intervals like so in /etc/cron.d/logs
* * * * * root /usr/local/bin/temp.sh 

with temp.sh containing
#!/bin/sh
file=/var/www/temp.txt
echo -n spare \ > $file
cat /sys/bus/w1/devices/28-0000062e511a/w1_slave | grep t | awk '{print $10}' | cut -d = -f 2 >> $file

echo -n comms_top \ >> $file
cat /sys/bus/w1/devices/28-0000062d26d0/w1_slave | grep t | awk '{print $10}' | cut -d = -f 2 >> $file

echo -n comms_bottom \ >> $file
cat /sys/bus/w1/devices/28-0000062e10ae/w1_slave | grep t | awk '{print $10}' | cut -d = -f 2 >> $file
Note the serials for the temp sensors were ascertained by individually plugging them in, making a note and appying labels physically to the device so I knew what I was monitoring.

So after the the data was grabbed and stored in a text file, you have to process it. I decided on PHP, cos it's easy and can be used easily on apache, which I can use to publish the data for view via a browser.
So after installing apache2, libapache2-mod-php5, php5-rrd,  rrdtool etc you need to input the data into an RRD

Using PHP and 
#!/usr/bin/php

 // Fetch current time
    $t = time();
    $filename1="/mnt/ramdisk/temp-spare.txt";
    $filename2="/mnt/ramdisk/temp-bottom.txt";
    $filename3="/mnt/ramdisk/temp-top.txt";

    $handle = fopen($filename1, "r");
    $contents1 = fread($handle, filesize($filename1));
    fclose ($handle);
    $contents1=(float)$contents1/1000;

    $handle = fopen($filename2, "r");
    $contents2 = fread($handle, filesize($filename2));
    fclose ($handle);
    $contents2=(float)$contents2/1000;

    $handle = fopen($filename3, "r");
    $contents3 = fread($handle, filesize($filename3));
    fclose ($handle);
    $contents3=(float)$contents3/1000;

   $option = array ("$t:$contents1:$contents2:$contents3");
        echo "$t ,$contents1, $contents2, $contents3 ";
    $ret = rrd_update("/mnt/ramdisk/temp-comms.rrd", $option);

    if (! $ret) {
              echo "<b>Graph error comms: </b>".rrd_error()."\n";
    }

then you've gotta create the GIFs
index.php
// for comms cupboard
function create_graph_temperature_comms ($output, $start, $title)
{
    $options = array(

    "--slope-mode",
    "--start", $start,
    "--title=$title",
    "--vertical-label=Temperature in oC",
    // oops got the top and bottom values mixed up on input
    "DEF:temp_spare=/mnt/ramdisk/temp-comms.rrd:spare:AVERAGE",
    "DEF:temp_top=/mnt/ramdisk/temp-comms.rrd:temp_bottom:AVERAGE",
    "DEF:temp_bottom=/mnt/ramdisk/temp-comms.rrd:temp_top:AVERAGE",

    "DEF:temp_sparemin=/mnt/ramdisk/temp-comms.rrd:spare:MIN",
    "DEF:temp_sparemax=/mnt/ramdisk/temp-comms.rrd:spare:MAX",
    "DEF:temp_topmin=/mnt/ramdisk/temp-comms.rrd:temp_top:MIN",
    "DEF:temp_topmax=/mnt/ramdisk/temp-comms.rrd:temp_top:MAX",
    "DEF:temp_bottommin=/mnt/ramdisk/temp-comms.rrd:temp_bottom:MIN",
    "DEF:temp_bottommax=/mnt/ramdisk/temp-comms.rrd:temp_bottom:MAX",
   
    "CDEF:ttemp_spare=temp_spare,1,*",
    "CDEF:ttemp_top=temp_top,1,*",
    "CDEF:ttemp_bottom=temp_bottom,1,*",
   
    "VDEF:vtemp_spare=temp_spare,AVERAGE",

    "LINE:ttemp_spare#00aa00:Spare:",
    "GPRINT:temp_spare:AVERAGE:Avg temp \\t %6.2lf",
    "GPRINT:temp_spare:LAST:Last temp \\t %6.2lf \\n",

    "LINE:ttemp_top#cc0000:Top:",
    "GPRINT:temp_top:AVERAGE:Avg temp \\t %6.2lf",
    "GPRINT:temp_top:LAST:Last temp \\t %6.2lf \\n",

    "LINE:ttemp_bottom#000088:Bottom:",

    "COMMENT:\\n",
    "--alt-autoscale",
    "--alt-y-grid",
   

   
  
    "GPRINT:vtemp_spare: test %6.2lf",
    );

    $ret = rrd_graph($output, $options);
        if (! $ret) {
        echo "<b>Graph error for temp comms</b>".rrd_error()."\n";
        }
}
And you'll get something like this: