After spending some time (quite a bit of it improving on my rusty
soldering iron skills) setting up some temperature sensors around the
home I came to the realization that I don't really care about graphs
plotting the past temperature - I just want a pretty picture telling me
how warm it is.
If this interests you, here are some pointers (instructions is really to
big a word) to get you on your way to something similar.
My goal was to set up digitemp so that the output could be parsed into a
scalable vector graphic representing my floor layout. This image would
then be returned by my webserver whenever someone wants to see the
temperature.
Set up your sensors and get some readouts
For some excellent instructions on setting up the sensors see here: http://www.instructables.com/id/Temperature-sensor--weatherstation/?ALLSTEPS.
I can only recommend using the DS1820 sensors and digitemp, as getting
everything running is really cheap - I bought everything twice not
trusting my soldering skills and still had a BOM of < 20€. Also using
telephone cable to wire everything up is also simple to do.
I ended up building the 'improved' serial connector which supplies power
on a separate line instead of on the data line - as I wanted to make
sure even if I run wires all over the place I will still get a stable
connection. And because (as stated) using telephone cable meant I had
some cables spare for the power line. See instructions here (German -
but the schematics should be understandable): http://www.lax.priv.at/digitemp/
Once you are finished you should be able to run the folowing command to
read the temperature output of your connected sensors.
----
digitemp -a
----
Create a SVG of your floor layout
A SVG is a scaleable vector graphic. The good thing about them is, that
- uncompressed - they are simply xml files, which makes them extremely
easy to change on the fly. Using Inkscape, I drew some lines
representing my outer walls and then created grey rectangles for each
room. The colour will be replaced by the temperature colour later. Make
sure you only create one shape for each room - as that will make things
easier later.
Then enter some text (e.g. two question marks) in each room - this will
be replaced by the temperature as number.
Finally (not really necessary) I added a scale, displaying each
temperature in 1 degree steps on top of a colour range representing each
temperature.
If you are using Inkscape (or probably any SVG editor) you should now
edit the IDs of your room shapes/rectangles to title<number> and
tspan_<number>. Here each number corresponds to a room as identified by
digitemp. (Just start with 0 and add 1 for each room - more on that
later).
Because I am calling cthulhu and
parsing the svg xml using a regex, we will need to make sure that the
XML attributes are in the right order. The 'fill' attribute for the room
shapes/rectangles needs to be just in front of their 'title
id=title<number>' element.
My resulting SVG can be downloaded here,
I assume that will clear things up.
Aside - convert temperature into a colour range
To make the temperature nice and easy to read, I wanted to replace the
background colour of each room with a corresponding colour - red for
hot, green for warm and blue for cold.
I did this by plotting the RGB values of the colour range I added to my
SVG above and then created several linear functions to increase/decrease
the individual RGB values to stay as close to the colour range as above.
The following table describes my colour steps (which are entirely
arbitrary)
Temperature
|
Red Value
|
Green Value
|
Blue Value
|
<11
|
FF
|
00
|
FF
|
<15.8
|
FF->00
|
00
|
FF
|
<19.82
|
00
|
00->FF
|
FF
|
<21.41
|
00
|
FF
|
FF->00
|
<26.92
|
00->FF
|
FF
|
00
|
<32.11
|
FF
|
FF->00
|
00
|
else
|
FF
|
00
|
00
|
Combine everything for your webserver
To make it easier to read the digitemp output, I reconfigured the
digitemprc file slightly to produce a very minimal output: <room
number>:<temperature>.
----
TTY /dev/ttyUSB0
READ_TIME 1000
LOG_TYPE 1
LOG_FORMAT "%s:%.2C"
CNT_FORMAT "%m %d %H:%M:%S Sensor %s #%n %C"
HUM_FORMAT "%m %d %H:%M:%S Sensor %s C: %.2C H: %h%%"
SENSORS 4
ROM 0 0xAB 0xCD 0xEF 0x01 0x02 0x03 0x04 0x05
ROM 1 0xAB 0xCD 0xEF 0x01 0x02 0x03 0x04 0x06
ROM 2 0xAB 0xCD 0xEF 0x01 0x02 0x03 0x04 0x07
ROM 3 0xAB 0xCD 0xEF 0x01 0x02 0x03 0x04 0x08
----
You will need to rearrange your sensors to fit in with the room
numbering that you used in your svg above. To make that easier just hold
each sensors in your hand for a few minutes before taking a new readout.
The warm sensor will be in the room you are in.
As this was a quick hack, I simply ended up hooking up a bash script as a
cgi response for my webserver.
The script calls digitemp using the config file above, and then creates
color values for each temperature response.
The result is then passed into the svg which it assumes to be in the
same directory.
----
#!/bin/bash
echo "Content-type: image/svg+xml; charset=UTF-8"
echo ""
# Get the SVG into a var
image=$(cat ./Grundriss.svg)
# First get temperatures into array temps
#digitemp -q -a -c /<location of your config file>/digitemprc
temps=$(digitemp -q -a -c /<location of your config file>/digitemprc)
# Now we build up a regex using these strings.
# fill:#949494">\n<title id="title0
# and id="tspan_0">??</tspan
for x in $temps
do
id=$(echo $x | cut -f1 -d:)
temp=$(echo $x | cut -f2 -d: | sed 's/\./\\./g')
temp_num=$(echo $x | cut -f2 -d:)
red="00"
green="00"
blue="00"
if (( $(bc <<< "$temp_num < 11") == 1 )); then
red="FF"
green="00"
blue="FF"
elif (( $(bc <<< "$temp_num < 15.8") == 1)); then
red=$(echo "obase=16; 255*-($temp_num-15.8)/4.8" | bc)
printf -v red "%02X" "0x"$red
green="00"
blue="FF"
elif (( $(bc <<< "$temp_num < 19.82") == 1)); then
red="00"
green=$(echo "obase=16; 255*($temp_num-15.8)/4.02" | bc)
printf -v green "%02X" "0x"$green
blue="FF"
elif (( $(bc <<< "$temp_num < 21.41") == 1)); then
red="00"
green="FF"
blue=$(echo "obase=16; 255*-($temp_num-21.41)/1.59" | bc)
printf -v blue "%02X" "0x"$blue
elif (( $(bc <<< "$temp_num < 26.96") == 1)); then
red=$(echo "obase=16; 255*($temp_num-21.41)/5.55" | bc)
printf -v red "%02X" "0x"$red
green="FF"
blue="00"
elif (( $(bc <<< "$temp_num < 32.11") == 1)); then
red=="FF"
green=$(echo "obase=16; 255*-($temp_num-32.11)/5.15" | bc)
printf -v green "%02X" "0x"$green
blue="00"
else
red="FF"
green="00"
blue="00"
fi
patterncf='fill:#949494"><title id="title'$id'">'
patterncr='fill:#'$red$green$blue'"><title id="title'$id'">'
# echo $patterncf
# echo $patterncr
image=$(sed -e s/"$patterncf"/"$patterncr"/g <(echo $image))
patternf='id="tspan_'$id'">??<\/tspan'
patternr='id="tspan_'$id'">'$temp'<\/tspan'
image=$(sed -e s/"$patternf"/"$patternr"/g <(echo $image))
done
echo $image
exit 0
----
I have embedded the output as image in a web page. You can of course do
something else with it.