├── README
├── monitor.py
├── templog.db
└── webgui.py
/README:
--------------------------------------------------------------------------------
1 | Raspberry Pi Temperature Logger
2 | ===============================
3 |
4 | This repo contains code for a Raspberry Pi temperature logger which uses SQLite to store data read from a DS18B20 sensor. You can see more details here:
5 | http://raspberrywebserver.com/cgiscripting/rpi-temperature-logger/building-an-sqlite-temperature-logger.html
6 |
7 | In webgui.py, there are several lines that contain hardcoded dates so that you can use the script with the sample database provided. There is an equivalent version of each of these lines that uses 'now' instead of a hardcoded timestamp. If you want to view data you've collected yourself, you should uncomment the lines that use 'now', and comment out the lines that have a hardocded date. See webgui.py, lines 45, 117, 122, 127 and 148.
8 |
--------------------------------------------------------------------------------
/monitor.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | import sqlite3
4 |
5 | import os
6 | import time
7 | import glob
8 |
9 | # global variables
10 | speriod=(15*60)-1
11 | dbname='/var/www/templog.db'
12 |
13 |
14 |
15 | # store the temperature in the database
16 | def log_temperature(temp):
17 |
18 | conn=sqlite3.connect(dbname)
19 | curs=conn.cursor()
20 |
21 | curs.execute("INSERT INTO temps values(datetime('now'), (?))", (temp,))
22 |
23 | # commit the changes
24 | conn.commit()
25 |
26 | conn.close()
27 |
28 |
29 | # display the contents of the database
30 | def display_data():
31 |
32 | conn=sqlite3.connect(dbname)
33 | curs=conn.cursor()
34 |
35 | for row in curs.execute("SELECT * FROM temps"):
36 | print str(row[0])+" "+str(row[1])
37 |
38 | conn.close()
39 |
40 |
41 |
42 | # get temerature
43 | # returns None on error, or the temperature as a float
44 | def get_temp(devicefile):
45 |
46 | try:
47 | fileobj = open(devicefile,'r')
48 | lines = fileobj.readlines()
49 | fileobj.close()
50 | except:
51 | return None
52 |
53 | # get the status from the end of line 1
54 | status = lines[0][-4:-1]
55 |
56 | # is the status is ok, get the temperature from line 2
57 | if status=="YES":
58 | print status
59 | tempstr= lines[1][-6:-1]
60 | tempvalue=float(tempstr)/1000
61 | print tempvalue
62 | return tempvalue
63 | else:
64 | print "There was an error."
65 | return None
66 |
67 |
68 |
69 | # main function
70 | # This is where the program starts
71 | def main():
72 |
73 | # enable kernel modules
74 | os.system('sudo modprobe w1-gpio')
75 | os.system('sudo modprobe w1-therm')
76 |
77 | # search for a device file that starts with 28
78 | devicelist = glob.glob('/sys/bus/w1/devices/28*')
79 | if devicelist=='':
80 | return None
81 | else:
82 | # append /w1slave to the device file
83 | w1devicefile = devicelist[0] + '/w1_slave'
84 |
85 |
86 | # while True:
87 |
88 | # get the temperature from the device file
89 | temperature = get_temp(w1devicefile)
90 | if temperature != None:
91 | print "temperature="+str(temperature)
92 | else:
93 | # Sometimes reads fail on the first attempt
94 | # so we need to retry
95 | temperature = get_temp(w1devicefile)
96 | print "temperature="+str(temperature)
97 |
98 | # Store the temperature in the database
99 | log_temperature(temperature)
100 |
101 | # display the contents of the database
102 | # display_data()
103 |
104 | # time.sleep(speriod)
105 |
106 |
107 | if __name__=="__main__":
108 | main()
109 |
110 |
111 |
112 |
113 |
--------------------------------------------------------------------------------
/templog.db:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Pyplate/rpi_temp_logger/8e87abbff03f2c33821ca9e81c73c717261c6744/templog.db
--------------------------------------------------------------------------------
/webgui.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | import sqlite3
4 | import sys
5 | import cgi
6 | import cgitb
7 |
8 |
9 | # global variables
10 | speriod=(15*60)-1
11 | dbname='/var/www/templog.db'
12 |
13 |
14 |
15 | # print the HTTP header
16 | def printHTTPheader():
17 | print "Content-type: text/html\n\n"
18 |
19 |
20 |
21 | # print the HTML head section
22 | # arguments are the page title and the table for the chart
23 | def printHTMLHead(title, table):
24 | print "
"
25 | print " "
26 | print title
27 | print " "
28 |
29 | print_graph_script(table)
30 |
31 | print ""
32 |
33 |
34 | # get data from the database
35 | # if an interval is passed,
36 | # return a list of records from the database
37 | def get_data(interval):
38 |
39 | conn=sqlite3.connect(dbname)
40 | curs=conn.cursor()
41 |
42 | if interval == None:
43 | curs.execute("SELECT * FROM temps")
44 | else:
45 | # curs.execute("SELECT * FROM temps WHERE timestamp>datetime('now','-%s hours')" % interval)
46 | curs.execute("SELECT * FROM temps WHERE timestamp>datetime('2013-09-19 21:30:02','-%s hours') AND timestamp<=datetime('2013-09-19 21:31:02')" % interval)
47 |
48 | rows=curs.fetchall()
49 |
50 | conn.close()
51 |
52 | return rows
53 |
54 |
55 | # convert rows from database into a javascript table
56 | def create_table(rows):
57 | chart_table=""
58 |
59 | for row in rows[:-1]:
60 | rowstr="['{0}', {1}],\n".format(str(row[0]),str(row[1]))
61 | chart_table+=rowstr
62 |
63 | row=rows[-1]
64 | rowstr="['{0}', {1}]\n".format(str(row[0]),str(row[1]))
65 | chart_table+=rowstr
66 |
67 | return chart_table
68 |
69 |
70 | # print the javascript to generate the chart
71 | # pass the table generated from the database info
72 | def print_graph_script(table):
73 |
74 | # google chart snippet
75 | chart_code="""
76 |
77 | """
94 |
95 | print chart_code % (table)
96 |
97 |
98 |
99 |
100 | # print the div that contains the graph
101 | def show_graph():
102 | print "Temperature Chart
"
103 | print ''
104 |
105 |
106 |
107 | # connect to the db and show some stats
108 | # argument option is the number of hours
109 | def show_stats(option):
110 |
111 | conn=sqlite3.connect(dbname)
112 | curs=conn.cursor()
113 |
114 | if option is None:
115 | option = str(24)
116 |
117 | # curs.execute("SELECT timestamp,max(temp) FROM temps WHERE timestamp>datetime('now','-%s hour') AND timestamp<=datetime('now')" % option)
118 | curs.execute("SELECT timestamp,max(temp) FROM temps WHERE timestamp>datetime('2013-09-19 21:30:02','-%s hour') AND timestamp<=datetime('2013-09-19 21:31:02')" % option)
119 | rowmax=curs.fetchone()
120 | rowstrmax="{0}   {1}C".format(str(rowmax[0]),str(rowmax[1]))
121 |
122 | # curs.execute("SELECT timestamp,min(temp) FROM temps WHERE timestamp>datetime('now','-%s hour') AND timestamp<=datetime('now')" % option)
123 | curs.execute("SELECT timestamp,min(temp) FROM temps WHERE timestamp>datetime('2013-09-19 21:30:02','-%s hour') AND timestamp<=datetime('2013-09-19 21:31:02')" % option)
124 | rowmin=curs.fetchone()
125 | rowstrmin="{0}   {1}C".format(str(rowmin[0]),str(rowmin[1]))
126 |
127 | # curs.execute("SELECT avg(temp) FROM temps WHERE timestamp>datetime('now','-%s hour') AND timestamp<=datetime('now')" % option)
128 | curs.execute("SELECT avg(temp) FROM temps WHERE timestamp>datetime('2013-09-19 21:30:02','-%s hour') AND timestamp<=datetime('2013-09-19 21:31:02')" % option)
129 | rowavg=curs.fetchone()
130 |
131 |
132 | print "
"
133 |
134 |
135 | print "Minumum temperature 
"
136 | print rowstrmin
137 | print "Maximum temperature
"
138 | print rowstrmax
139 | print "Average temperature
"
140 | print "%.3f" % rowavg+"C"
141 |
142 | print "
"
143 |
144 | print "In the last hour:
"
145 | print ""
146 | print "Date/Time | Temperature |
"
147 |
148 | # rows=curs.execute("SELECT * FROM temps WHERE timestamp>datetime('new','-1 hour') AND timestamp<=datetime('new')")
149 | rows=curs.execute("SELECT * FROM temps WHERE timestamp>datetime('2013-09-19 21:30:02','-1 hour') AND timestamp<=datetime('2013-09-19 21:31:02')")
150 | for row in rows:
151 | rowstr="{0} | {1}C |
".format(str(row[0]),str(row[1]))
152 | print rowstr
153 | print "
"
154 |
155 | print "
"
156 |
157 | conn.close()
158 |
159 |
160 |
161 |
162 | def print_time_selector(option):
163 |
164 | print """"""
194 |
195 |
196 | # check that the option is valid
197 | # and not an SQL injection
198 | def validate_input(option_str):
199 | # check that the option string represents a number
200 | if option_str.isalnum():
201 | # check that the option is within a specific range
202 | if int(option_str) > 0 and int(option_str) <= 24:
203 | return option_str
204 | else:
205 | return None
206 | else:
207 | return None
208 |
209 |
210 | #return the option passed to the script
211 | def get_option():
212 | form=cgi.FieldStorage()
213 | if "timeinterval" in form:
214 | option = form["timeinterval"].value
215 | return validate_input (option)
216 | else:
217 | return None
218 |
219 |
220 |
221 |
222 | # main function
223 | # This is where the program starts
224 | def main():
225 |
226 | cgitb.enable()
227 |
228 | # get options that may have been passed to this script
229 | option=get_option()
230 |
231 | if option is None:
232 | option = str(24)
233 |
234 | # get data from the database
235 | records=get_data(option)
236 |
237 | # print the HTTP header
238 | printHTTPheader()
239 |
240 | if len(records) != 0:
241 | # convert the data into a table
242 | table=create_table(records)
243 | else:
244 | print "No data found"
245 | return
246 |
247 | # start printing the page
248 | print ""
249 | # print the head section including the table
250 | # used by the javascript for the chart
251 | printHTMLHead("Raspberry Pi Temperature Logger", table)
252 |
253 | # print the page body
254 | print ""
255 | print "Raspberry Pi Temperature Logger
"
256 | print "
"
257 | print_time_selector(option)
258 | show_graph()
259 | show_stats(option)
260 | print ""
261 | print ""
262 |
263 | sys.stdout.flush()
264 |
265 | if __name__=="__main__":
266 | main()
267 |
268 |
269 |
270 |
271 |
--------------------------------------------------------------------------------