First Raspberry Pi Project
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!