Problem we are solving here is.
1. User raspberry pi to get the room temperature
2. Store the temp in a sqlite database.
3. Display the results in a neat graph using a webpage.
-- create get temp.py to get the temperature
#!/usr/bin/env python
import sqlite3
import os
import time
import glob
# global variables
speriod=(15*60)-1
dbname='/home/pi/tempdb/mydatabase.db'
# store the temperature in the database
def log_temperature(temp):
conn=sqlite3.connect(dbname)
curs=conn.cursor()
# bavita added , 'localtime' to get the local time from machine else it is showing GMT
curs.execute("INSERT INTO temps values(datetime('now', 'localtime'), (?))", (temp,))
# commit the changes
conn.commit()
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)
if __name__=="__main__":
main()
-- test apache
open the bowser from a machine other than the pi and type the ip address of pi like below and hit enter
http://192.168.0.2/
The page should display something like below:
-- Solder sensor and resistor as described below and then use the wire to connect them to GPIO.
-- The final product should looks something like below:
-- After the setup perform a quick test on sensor and see if it works and that is done as below:
Here temp is 16687 / 1000 = 16.687 C
Please note that if the black sensor is getting too hot then you have soldered it other way around, change the pins and it should be fine.
-- Enable cgi-bin on apache
We will be writing the code in python and in order for that code to display content on webpage we need to change apache config to enable cgi scripts.
Go to /usr/lib/cgi-bin and create sensor.py with chmod 777
Now go to /etc/apache2/sites-available
edit file called default and add below in red color
<Directory "/usr/lib/cgi-bin">
AddHandler cgi-script .py
AllowOverride None
Options +ExecCGI -MultiViews +SymLinksIfOwnerMatch
Order allow,deny
Allow from all
</Directory>
Note the bit in blue /usr/lib/cgi-bin this is where your web application sensor.py should go and work in browser.
-- code for sensor.py
#!/usr/bin/env python
import sqlite3
import sys
import cgi
import cgitb
# global variables
speriod=(15*60)-1
#dbname='/var/www/mydatabase.db'
dbname='/home/pi/tempdb/mydatabase.db'
# print the HTTP header
def printHTTPheader():
print "Content-type: text/html\n\n"
# print the HTML head section
# arguments are the page title and the table for the chart
def printHTMLHead(title, table):
print "<head>"
print " <title>"
print title
print " </title>"
print_graph_script(table)
print "</head>"
# get data from the database
# if an interval is passed,
# return a list of records from the database
def get_data(interval):
conn=sqlite3.connect(dbname)
curs=conn.cursor()
if interval == None:
curs.execute("SELECT * FROM temps")
else:
curs.execute("SELECT * FROM temps WHERE temptime>datetime('now','localtime','-%s hours')" % interval)
# curs.execute("SELECT * FROM temps WHERE temptime>datetime('2013-09-19 21:30:02','-%s hours') AND temptime<=datetime('2013-09-19 21:31:02')" % interval)
rows=curs.fetchall()
conn.close()
return rows
# convert rows from database into a javascript table
def create_table(rows):
chart_table=""
for row in rows[:-1]:
rowstr="['{0}', {1}],\n".format(str(row[0]),str(row[1]))
chart_table+=rowstr
row=rows[-1]
rowstr="['{0}', {1}]\n".format(str(row[0]),str(row[1]))
chart_table+=rowstr
return chart_table
# print the javascript to generate the chart
# pass the table generated from the database info
def print_graph_script(table):
# google chart snippet
chart_code="""
<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 = google.visualization.arrayToDataTable([ ['Time', 'Temperature'],%s ]);
var options = {
hAxis: {
title: 'Time'
},
vAxis: {
title: 'Temperature'
},
title: 'Temperature Vs Time',
backgroundColor: '#f1f8e9'
};
var chart = new google.visualization.LineChart(document.getElementById('chart_div'));
chart.draw(data, options);
}
</script>"""
print chart_code % (table)
# print the div that contains the graph
def show_graph():
print "<h2>Temperature Chart</h2>"
# Bavita commented below to make the graph bigger
# print '<div id="chart_div" style="width: 900px; height: 500px;"></div>'
print '<div id="chart_div" style="width: 1300px; height: 700px;"></div>'
# connect to the db and show some stats
# argument option is the number of hours
def show_stats(option):
conn=sqlite3.connect(dbname)
curs=conn.cursor()
if option is None:
option = str(24)
curs.execute("SELECT temptime,max(temp) FROM temps WHERE temptime>datetime('now','localtime','-%s hour') AND temptime<=datetime('now','localtime')" % option)
# curs.execute("SELECT temptime,max(temp) FROM temps WHERE temptime>datetime('2013-09-19 21:30:02','-%s hour') AND temptime<=datetime('2013-09-19 21:31:02')" % option)
rowmax=curs.fetchone()
rowstrmax="{0}   {1}C".format(str(rowmax[0]),str(rowmax[1]))
curs.execute("SELECT temptime,min(temp) FROM temps WHERE temptime>datetime('now','localtime','-%s hour') AND temptime<=datetime('now','localtime')" % option)
# curs.execute("SELECT temptime,min(temp) FROM temps WHERE temptime>datetime('2013-09-19 21:30:02','-%s hour') AND temptime<=datetime('2013-09-19 21:31:02')" % option)
rowmin=curs.fetchone()
rowstrmin="{0}   {1}C".format(str(rowmin[0]),str(rowmin[1]))
curs.execute("SELECT avg(temp) FROM temps WHERE temptime>datetime('now','localtime','-%s hour') AND temptime<=datetime('now','localtime')" % option)
# curs.execute("SELECT avg(temp) FROM temps WHERE temptime>datetime('2013-09-19 21:30:02','-%s hour') AND temptime<=datetime('2013-09-19 21:31:02')" % option)
rowavg=curs.fetchone()
curs.execute("select * from temps where temptime =(select max(temptime) FROM temps WHERE temptime>datetime('now','localtime','-1 hour') AND temptime<=datetime('now','localtime'))")
rowcurrent=curs.fetchone()
rowstrcurrent="{0}   {1}C".format(str(rowcurrent[0]),str(rowcurrent[1]))
print "<hr>"
print "<h2>Current temperature </h2>"
print rowstrcurrent
print "<h2>Minumum temperature </h2>"
print rowstrmin
print "<h2>Maximum temperature</h2>"
print rowstrmax
print "<h2>Average temperature</h2>"
print "%.3f" % rowavg+"C"
print "<hr>"
print "<h2>In the last hour:</h2>"
print "<table>"
print "<tr><td><strong>Date/Time</strong></td><td><strong>Temperature</strong></td></tr>"
#rows=curs.execute("SELECT * FROM temps WHERE temptime>datetime('now','-1 hour') AND temptime<=datetime('now')")
# display the temp in last hour under "In the last hour"
rows=curs.execute("SELECT * FROM temps WHERE temptime>datetime('now','localtime','-1 hour') AND temptime<=datetime('now','localtime')")
# rows=curs.execute("SELECT * FROM temps WHERE temptime>datetime('2013-09-19 21:30:02','-1 hour') AND temptime<=datetime('2013-09-19 21:31:02')")
for row in rows:
rowstr="<tr><td>{0}  </td><td>{1}C</td></tr>".format(str(row[0]),str(row[1]))
print rowstr
print "</table>"
print "<hr>"
conn.close()
def print_time_selector(option):
print """<form action="/cgi-bin/webgui.py" method="POST">
Show the temperature logs for
<select name="timeinterval">"""
if option is not None:
if option == "1":
print "<option value=\"1\" selected=\"selected\">the last 1 hours</option>"
else:
print "<option value=\"1\">the last 1 hours</option>"
if option == "2":
print "<option value=\"2\" selected=\"selected\">the last 2 hours</option>"
else:
print "<option value=\"2\">the last 2 hours</option>"
if option == "3":
print "<option value=\"3\" selected=\"selected\">the last 3 hours</option>"
else:
print "<option value=\"3\">the last 3 hours</option>"
if option == "6":
print "<option value=\"6\" selected=\"selected\">the last 6 hours</option>"
else:
print "<option value=\"6\">the last 6 hours</option>"
if option == "12":
print "<option value=\"12\" selected=\"selected\">the last 12 hours</option>"
else:
print "<option value=\"12\">the last 12 hours</option>"
if option == "24":
print "<option value=\"24\" selected=\"selected\">the last 24 hours</option>"
else:
print "<option value=\"24\">the last 24 hours</option>"
if option == "48":
print "<option value=\"48\" selected=\"selected\">the last 2 Days</option>"
else:
print "<option value=\"48\">the last 2 days</option>"
if option == "168":
print "<option value=\"168\" selected=\"selected\">the last 7 Days</option>"
else:
print "<option value=\"168\">the last 7 days</option>"
if option == "336":
print "<option value=\"336\" selected=\"selected\">the last 14 Days</option>"
else:
print "<option value=\"336\">the last 14 days</option>"
if option == "720":
print "<option value=\"720\" selected=\"selected\">the last 30 Days</option>"
else:
print "<option value=\"720\">the last 30 days</option>"
if option == "4320":
print "<option value=\"4320\" selected=\"selected\">the last 180 Days</option>"
else:
print "<option value=\"4320\">the last 180 days</option>"
else:
print """
<option value="1">the last 1 hours</option>
<option value="2">the last 2 hours</option>
<option value="3">the last 3 hours</option>
<option value="6">the last 6 hours</option>
<option value="12">the last 12 hours</option>
<option value="24" selected="selected">the last 24 hours</option>
<option value="48">the last 2 Day</option>
<option value="168">the last 7 Day</option>
<option value="336">the last 14 Day</option>
<option value="720">the last 30 Day</option>
<option value="4320">the last 180 Day</option>
"""
print """ </select>
<input type="submit" value="Display">
</form>"""
# check that the option is valid
# and not an SQL injection
def validate_input(option_str):
# check that the option string represents a number
if option_str.isalnum():
# check that the option is within a specific range
if int(option_str) > 0 and int(option_str) <= 4320:
return option_str
else:
return None
else:
return None
#return the option passed to the script
def get_option():
form=cgi.FieldStorage()
if "timeinterval" in form:
option = form["timeinterval"].value
return validate_input (option)
else:
return None
# main function
# This is where the program starts
def main():
cgitb.enable()
# get options that may have been passed to this script
option=get_option()
if option is None:
option = str(24)
# get data from the database
records=get_data(option)
# print the HTTP header
printHTTPheader()
if len(records) != 0:
# convert the data into a table
table=create_table(records)
else:
print "No data found"
return
# start printing the page
print "<html>"
# print the head section including the table
# used by the javascript for the chart
printHTMLHead("Raspberry Pi Temperature Logger", table)
# print the page body
print "<body>"
print "<h1>Raspberry Pi Temperature Logger</h1>"
print "<hr>"
print_time_selector(option)
show_graph()
show_stats(option)
print "</body>"
print "</html>"
sys.stdout.flush()
if __name__=="__main__":
main()
-- Test URL
Now we can test the URL as
http://192.168.0.2/cgi-bin/sensor.py