Just got my self a DS18D20 and I thought it will be good to build a controller to record temperature.
I am using these two websites to help me start:
http://raspberrywebserver.com/cgiscripting/rpi-temperature-logger/building-an-sqlite-temperature-logger.html
https://www.cl.cam.ac.uk/projects/raspberrypi/tutorials/temperature/
In the second website I understood the basic to connect a DS18B20 ![]()
Then the code in python to get the readings:
#!/usr/bin/env python
import os
import glob
import time
# load the kernel modules needed to handle the sensor
os.system('modprobe w1-gpio')
os.system('modprobe w1-therm')
# find the path of a sensor directory that starts with 28
devicelist = glob.glob('/sys/bus/w1/devices/28*')
# append the device file name to get the absolute path of the sensor
devicefile = devicelist[0] + '/w1_slave'
# open the file representing the sensor.
fileobj = open(devicefile,'r')
lines = fileobj.readlines()
fileobj.close()
# print the lines read from the sensor apart from the extra \n chars
#print lines[0][:-1]
#print lines[1][:-1]
# Split the text with new lines (\n) and select the second line.
secondline = lines[1]
# Split the line into words, referring to the spaces, and select the 10th word (counting from 0).
temperaturedata = secondline.split(" ")[9]
# The first two characters are "t=", so get rid of those and convert the temperature from a string to a number.
temperature = float(temperaturedata[2:])
# Put the decimal point in the right place and display it.
temperature = temperature / 1000
print temperature
Then on the other URL I started to log my entries. Here is the script:
#!/usr/bin/env python
import sqlite3
import os
import time
import glob
# global variables
speriod=(15*60)-1
dbname='/home/pi/templog.db'
# store the temperature in the database
def log_temperature(temp):
conn=sqlite3.connect(dbname)
curs=conn.cursor()
curs.execute("INSERT INTO temps values(datetime('now'), (?))", (temp,))
# commit the changes
conn.commit()
conn.close()
# display the contents of the database
def display_data():
conn=sqlite3.connect(dbname)
curs=conn.cursor()
for row in curs.execute("SELECT * FROM temps"):
print str(row[0])+" "+str(row[1])
conn.close()
# get temerature
# returns None on error, or the temperature as a float
def get_temp(devicefile):
try:
fileobj = open(devicefile,'r')
lines = fileobj.readlines()
fileobj.close()
except:
return None
# get the status from the end of line 1
status = lines[0][-4:-1]
# is the status is ok, get the temperature from line 2
if status=="YES":
print status
tempstr= lines[1][-6:-1]
tempvalue=float(tempstr)/1000
print tempvalue
return tempvalue
else:
print "There was an error."
return None
# main function
# This is where the program starts
def main():
# enable kernel modules
os.system('sudo modprobe w1-gpio')
os.system('sudo modprobe w1-therm')
# search for a device file that starts with 28
devicelist = glob.glob('/sys/bus/w1/devices/28*')
if devicelist=='':
return None
else:
# append /w1slave to the device file
w1devicefile = devicelist[0] + '/w1_slave'
# while True:
# get the temperature from the device file
temperature = get_temp(w1devicefile)
if temperature != None:
print "temperature="+str(temperature)
else:
# Sometimes reads fail on the first attempt
# so we need to retry
temperature = get_temp(w1devicefile)
print "temperature="+str(temperature)
# Store the temperature in the database
log_temperature(temperature)
# display the contents of the database
# display_data()
# time.sleep(speriod)
if __name__=="__main__":
main()
Make sure you go through the steps to create the sqlite db first.
Now I have a crontab job that save my reading every 15 minutes and now I need to show those reading. I used to run my Pi as webserver (LAMP) but I always thought it was a bit too much for a RPi. So I searched the web for a python web REST service and I found this nifty website: http://webpy.org/.
I have to say it work like a charm. The overhead in term of resources is way less then a LAMP and it gets the job done. Is extremely simple and quick to implement.
I started with some good examples:
http://www.milocreek.com/wiki/index.php/GettingStarted
http://www.dreamsyssoft.com/blog/blog.php?/archives/6-Create-a-simple-REST-web-service-with-Python.html
I created a rest service to broadcast reading to my web server:
#!/usr/bin/env python
import web
from web.template import render
db = web.database(dbn='sqlite', db='/home/pi/templog.db')
urls = (
'/', 'index',
'/(.*)','get_temp'
)
app = web.application(urls, globals())
class index:
def GET(self):
temps = db.query("select * from temps where timestamp>datetime('now','-24 hours')") #select('temps')
output= ''
for temp in temps:
output += ",['"+str(temp.timestamp)+"',"+str(temp.temp)+"]"
return output
class get_temp:
def GET(self,hours):
temps = db.query("select * from temps where timestamp>datetime('now','-%s hours')" % hours) #select('temps')
output= ''
for temp in temps:
output += ",['"+str(temp.timestamp)+"',"+str(temp.temp)+"]"
return output
if __name__ == "__main__":
app.run()
The rest service will be broadcast on port 8080 by default. Just type http://piipaddress:8080 and you will see the data.
To start the rest service when the Pi reboot just call the python code above to crontap:
sudo crontab -e
Then add the code below to the bottom of the script.
@reboot /home/pi/rest.py
The last step is pick the data up from my webserver (LAMP) and use Google API to present some fancy graphic. Here is the code:
<!DOCTYPE html>
<html>
<head>
<title>Temperature Log</title>
<meta http-equiv="refresh" content="900" />
<link rel="stylesheet" type="text/css" href="local.css" />
<script src="//code.jquery.com/jquery-1.10.2.js"></script>
<script type="text/javascript" src="https://www.google.com/jsapi"></script>
<script>
$(document).ready(function(){
<?php if(!isset($_REQUEST['interval'])) { echo "$('#interval option[value=24]').attr('selected', 'selected');"; } ?>
$('#intDis').html($('#interval option:selected').text());
$('#interval').change(function () {
location.href = 'http://home.robertomignucci.co.uk?interval=' + $('#interval option:selected').val()
});
});
google.load("visualization", "1", {packages:["corechart"]});
google.setOnLoadCallback(drawChart);
function drawChart() {
var data = google.visualization.arrayToDataTable([
['Time', 'Temperature']
<?php
if (isset($_REQUEST['interval']))
{
// param was set in the query string
if(!empty($_REQUEST['interval']))
{
$hours = $_GET['interval'];
echo file_get_contents("http://RPiIPaddress:8080/" . $hours);
//echo $hours;
}
}
else
{
echo file_get_contents("http://RPiIPaddress:8080/");
}
?>
]);
var options = {
title: 'Temperature Log'
};
var chart = new google.visualization.LineChart
(document.getElementById('chart_div'));
chart.draw(data, options);
}
</script>
</head>
<body>
<h1>Temperature Report</h1>
<div>
Selected time span: <select id="interval">
<option value="6" <?php if(isset($_REQUEST['interval'])) {if ($_GET['interval'] == 6) {echo "selected";}} ?> >6hrs</option>
<option value="12" <?php if(isset($_REQUEST['interval'])) {if ($_GET['interval'] == 12) {echo "selected";}} ?> >12hrs</option>
<option value="24" <?php if(isset($_REQUEST['interval'])) {if ($_GET['interval'] == 24) {echo "selected";}} ?> >24hrs</option>
<option value="48" <?php if(isset($_REQUEST['interval'])) {if ($_GET['interval'] == 48) {echo "selected";}} ?> >48hrs</option>
<option value="168" <?php if(isset($_REQUEST['interval'])) {if ($_GET['interval'] == 168) {echo "selected";}} ?>>1 week</option>
<option value="236" <?php if(isset($_REQUEST['interval'])) {if ($_GET['interval'] == 236) {echo "selected";}} ?> >2 weeks</option>
</select> last <span id="intDis"></span> (UCT)</div>
<div id="chart_div" style="width: 900px; height: 500px;"></div>
</body>
</html>
Here is the result: http://home.robertomignucci.co.uk/
I hope this will be useful to you. Have fun with it!