diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..1377554
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
+*.swp
diff --git a/README b/README
deleted file mode 100644
index 5b59f85..0000000
--- a/README
+++ /dev/null
@@ -1,7 +0,0 @@
-Raspberry Pi Temperature Logger
-===============================
-
-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:
-http://raspberrywebserver.com/cgiscripting/rpi-temperature-logger/building-an-sqlite-temperature-logger.html
-
-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.
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..a8312a5
--- /dev/null
+++ b/README.md
@@ -0,0 +1,8 @@
+#Raspberry Pi Temperature Logger
+This repo contains code for a Raspberry Pi temperature logger which uses SQLite to store data read from a DS18B20 sensor.
+
+#Installation:
+**Warning:** Your Raspberry Pi will reboot after installation to enable GPIO
+```bash
+cd && git clone https://github.com/poohzrn/rpi_temp_logger && cd ~/rpi_temp_logger && ./install.sh
+```
diff --git a/createDatabase.sql b/createDatabase.sql
new file mode 100644
index 0000000..f4d9bf9
--- /dev/null
+++ b/createDatabase.sql
@@ -0,0 +1,10 @@
+CREATE TABLE sensor_data (
+ sensor_id TEXT NOT NULL,
+ timestamp datetime NOT NULL DEFAULT (DATETIME(CURRENT_TIMESTAMP, 'LOCALTIME')),
+ value real NOT NULL
+);
+CREATE TABLE sensor (
+ sensor_id TEXT NOT NULL UNIQUE,
+ sensor_name TEXT NOT NULL DEFAULT 'SensorName',
+ PRIMARY KEY(sensor_id)
+);
diff --git a/devmonitor.py b/devmonitor.py
new file mode 100755
index 0000000..6afaeb7
--- /dev/null
+++ b/devmonitor.py
@@ -0,0 +1,38 @@
+#!/usr/bin/env python
+
+import sqlite3
+import glob
+import random
+import commands
+
+# global variables
+dbname='/var/www/tmplog/tempdb2.db'
+
+# store the temperature in the database
+def log_temperature(iD, temp):
+ conn=sqlite3.connect(dbname)
+ curs=conn.cursor()
+ insertDeviceQuery = "INSERT OR IGNORE INTO sensor (sensor_id) VALUES('"+str(iD)+"');"
+ curs.execute(insertDeviceQuery);
+ insertDataQuery = "INSERT INTO sensor_data (sensor_id,value) VALUES('"+str(iD)+"','"+str(temp)+"');"
+ curs.execute(insertDataQuery);
+ # commit the changes
+ conn.commit()
+ conn.close()
+
+# main function
+# This is where the program starts
+def main():
+ devicelist = ['device1','device2',"device321"]
+ if devicelist=='':
+ # no devices
+ return None
+ else:
+ for device in devicelist:
+ temperature = random.uniform(0.0,45.0)
+ deviceid = device
+ print temperature
+ print deviceid
+ log_temperature(deviceid, temperature)
+if __name__=="__main__":
+ main()
diff --git a/install.sh b/install.sh
new file mode 100755
index 0000000..a80e202
--- /dev/null
+++ b/install.sh
@@ -0,0 +1,28 @@
+!#/usr/bin/env bash
+#Sudo access
+sudo -v
+sudo apt-get update
+sudo apt-get intsall apache2 -y
+sudo apt-get install sqlite3 -y
+sudo a2enmod mpm_prefork cgi
+sudo mkdir -p /var/www/tmplog
+cat ~/rpi_temp_logger/createDatabase.sql | sqlite3 tempdb2.db
+
+if [ -e /var/www/tmplog/tempdb2.db ]; then
+ sudo mv /var/www/tmplog ~/tempdb2.bak
+fi
+sudo cp ~/rpi_temp_logger/tmplog.conf /etc/apache2/sites-enabled
+sudo mv ~/rpi_temp_logger/tempdb2.db /var/www/tmplog
+sudo ln -s ~/rpi_temp_logger/monitor.py /usr/lib/cgi-bin/
+sudo ln -s ~/rpi_temp_logger/webgui.py /var/www/tmplog/index.py
+
+sudo chown www-data:www-data /usr/lib/cgi-bin/monitor.py
+sudo chown www-data:www-data /var/www/tmplog/tempdb2.db
+#Add Crontab to get data from sensors
+sudo crontab -l > currentCron
+sudo echo "* * * * * /usr/lib/cgi-bin/monitor.py" >> currentCron
+sudo crontab currentCron && sudo rm currentCron
+#enable GPIO
+sudo echo "dtoverlay=w1-gpio" >> /boot/config.txt
+#restart to enable GPIO
+sudo reboot now
diff --git a/monitor.py b/monitor.py
index b20a80e..f28b9e4 100755
--- a/monitor.py
+++ b/monitor.py
@@ -1,45 +1,39 @@
#!/usr/bin/env python
import sqlite3
-
import os
-import time
import glob
+import commands
# global variables
speriod=(15*60)-1
-dbname='/var/www/templog.db'
-
-
+dbname='/var/www/tmplog/tempdb2.db'
# store the temperature in the database
-def log_temperature(temp):
-
+def log_temperature(iD, temp):
conn=sqlite3.connect(dbname)
curs=conn.cursor()
-
- curs.execute("INSERT INTO temps values(datetime('now'), (?))", (temp,))
-
+ insertDeviceQuery = "INSERT OR IGNORE INTO sensor (sensor_id) VALUES('"+str(iD)+"');"
+ curs.execute(insertDeviceQuery);
+ insertDataQuery = "INSERT INTO sensor_data (sensor_id,value) VALUES('"+str(iD)+"','"+str(temp)+"');"
+ curs.execute(insertDataQuery);
# commit the changes
conn.commit()
-
conn.close()
-
# display the contents of the database
-def display_data():
-
+def display_data(iD):
conn=sqlite3.connect(dbname)
curs=conn.cursor()
-
- for row in curs.execute("SELECT * FROM temps"):
- print str(row[0])+" "+str(row[1])
-
+ getDevices = "SELECT * FROM sensor"
+ getSensorDataQuery = "SELECT * FROM sensor_data WHERE sensor_id =?"
+ for row in curs.execute(getSensorDataQuery, [iD]):
+ print str(row[0])+" "+str(row[1])+" "+str(row[2])
+ for row in curs.execute(getDevices):
+ print str(row[0])+" "+str(row[1])
conn.close()
-
-
-# get temerature
+# get temperature
# returns None on error, or the temperature as a float
def get_temp(devicefile):
@@ -64,8 +58,6 @@ def get_temp(devicefile):
print "There was an error."
return None
-
-
# main function
# This is where the program starts
def main():
@@ -75,38 +67,24 @@ def main():
os.system('sudo modprobe w1-therm')
# search for a device file that starts with 28
- devicelist = glob.glob('/sys/bus/w1/devices/28*')
+ deviceDir = '/sys/bus/w1/devices/'
+ devicelist = glob.glob(deviceDir + '28*')
+ print devicelist
if devicelist=='':
+ # no devices
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)
-
-
+ for w1devicefile in devicelist:
+ w1devicefile = w1devicefile + '/w1_slave'
+ # get the temperature from the device file
+ temperature = get_temp(w1devicefile)
+ while temperature == None:
+ temperature = get_temp(w1devicefile)
+
+ deviceid = w1devicefile.split("/")[5]
+ # Store the temperature in the database
+ log_temperature(deviceid, temperature)
+ #display_data(deviceid)
if __name__=="__main__":
main()
-
-
-
-
diff --git a/templog.db b/templog.db
deleted file mode 100644
index 99983d0..0000000
Binary files a/templog.db and /dev/null differ
diff --git a/tmplog.conf b/tmplog.conf
new file mode 100644
index 0000000..8c4bb5e
--- /dev/null
+++ b/tmplog.conf
@@ -0,0 +1,11 @@
+NameVirtualHost *:80
+
+
+ Options +ExecCGI
+ DirectoryIndex index.py
+
+ AddHandler cgi-script
+ DocumentRoot /var/www/tmplog
+ ErrorLog ${APACHE_LOG_DIR}/error.log
+ CustomLog ${APACHE_LOG_DIR}/access.log combined
+
diff --git a/webgui.py b/webgui.py
index a139980..71ada5a 100755
--- a/webgui.py
+++ b/webgui.py
@@ -2,22 +2,18 @@
import sqlite3
import sys
+import platform
+from collections import namedtuple
import cgi
import cgitb
-
# global variables
-speriod=(15*60)-1
-dbname='/var/www/templog.db'
-
-
+dbname='/var/www/tmplog/tempdb2.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):
@@ -25,52 +21,61 @@ def printHTMLHead(title, table):
print "
"
print title
print " "
-
print_graph_script(table)
-
print ""
-
-# get data from the database
-# if an interval is passed,
-# return a list of records from the database
-def get_data(interval):
-
+#Get the number of sensors
+def getSensorCount():
conn=sqlite3.connect(dbname)
curs=conn.cursor()
-
- if interval == None:
- curs.execute("SELECT * FROM temps")
- else:
-# curs.execute("SELECT * FROM temps WHERE timestamp>datetime('now','-%s hours')" % interval)
- 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)
-
- rows=curs.fetchall()
-
+ curs.execute("select count(DISTINCT sensor.sensor_id) from sensor;")
+ rows=curs.fetchone()
conn.close()
+ return int(format((rows[0])))
- return rows
-
+#get data from sensors based on a given interval
+#todo singleton
+def getSensorData(interval):
+ SensorDataRecord = namedtuple('sensor_data','name,timestamp,temperature')
+ conn=sqlite3.connect(dbname)
+ curs=conn.cursor()
+ if interval is None:
+ #uptimize - we dont need all data
+ #todo fixed time
+ curs.execute("SELECT sensor.sensor_name, timestamp, value FROM sensor_data,sensor WHERE timestamp>=datetime('now','-1 hours','+2 hours') AND sensor.sensor_id = sensor_data.sensor_id")
+ else:
+ curs.execute("SELECT sensor.sensor_name, timestamp, value FROM sensor_data,sensor WHERE timestamp>=datetime('now','-{0} hours','+2 hours') AND sensor.sensor_id = sensor_data.sensor_id".format(interval))
+ return map(SensorDataRecord._make,curs.fetchall())
# 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
-
+def createMultiTable(interval):
+ sensorCount = getSensorCount()
+ sensorData = getSensorData(interval)
+ dataTable = "['Time',"
+ for name in range(0,sensorCount - 1):
+ dataTable+="'{0}',".format(sensorData[name].name)
+ dataTable+="'{0}'],\n".format(sensorData[-1].name)#last sensor (-1) #sensorname[1]
+ dataTable+="['{0}',{1},".format(sensorData[0].timestamp[:-3],sensorData[0].temperature)
+ counter = 1
+ for data in sensorData[1:-1]:
+ if counter % sensorCount is 0:
+ dataTable+="],\n["
+ dataTable+="'{0}',".format(data.timestamp[:-3])
+ counter = 0
+ if counter is sensorCount:
+ dataTable+="]{0}".format(data.temperature)
+ counter = 0
+ if counter is sensorCount -1:
+ dataTable+="{0}".format(data.temperature)
+ elif counter is not sensorCount:
+ dataTable+="{0},".format(data.temperature)
+ counter += 1
+ dataTable+="'{0}']".format(sensorData[-1].temperature)
+ return dataTable
# 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="""
@@ -78,96 +83,67 @@ def print_graph_script(table):
google.load("visualization", "1", {packages:["corechart"]});
google.setOnLoadCallback(drawChart);
function drawChart() {
- var data = google.visualization.arrayToDataTable([
- ['Time', 'Temperature'],
-%s
- ]);
-
- var options = {
- title: 'Temperature'
- };
-
+ var data = google.visualization.arrayToDataTable([%s]);
+ var options = {title: 'Temperature', curveType: 'function'};
var chart = new google.visualization.LineChart(document.getElementById('chart_div'));
chart.draw(data, options);
}
"""
-
print chart_code % (table)
-
-
-
# print the div that contains the graph
def show_graph():
print "Temperature Chart
"
- print ''
-
-
+ print ''
# connect to the db and show some stats
# argument option is the number of hours
-def show_stats(option):
-
+def show_stats(interval):
conn=sqlite3.connect(dbname)
curs=conn.cursor()
+ if not interval:
+ interval = str(24)
- if option is None:
- option = str(24)
-
-# curs.execute("SELECT timestamp,max(temp) FROM temps WHERE timestamp>datetime('now','-%s hour') AND timestamp<=datetime('now')" % option)
- 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)
+ curs.execute("SELECT timestamp,max(value) FROM sensor_data WHERE timestamp>datetime('now','-%s hour') AND timestamp<=datetime('now','+2 hour')" % interval)
rowmax=curs.fetchone()
- rowstrmax="{0}   {1}C".format(str(rowmax[0]),str(rowmax[1]))
+ rowstrmax="{0} {1}C".format((str(rowmax[0]))[:-3],(str(rowmax[1]))[:4])
-# curs.execute("SELECT timestamp,min(temp) FROM temps WHERE timestamp>datetime('now','-%s hour') AND timestamp<=datetime('now')" % option)
- 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)
+ curs.execute("SELECT timestamp,min(value) FROM sensor_data WHERE timestamp>datetime('now','-%s hour') AND timestamp<=datetime('now','+2 hour')" % interval)
rowmin=curs.fetchone()
- rowstrmin="{0}   {1}C".format(str(rowmin[0]),str(rowmin[1]))
+ rowstrmin="{0} {1}C".format((str(rowmin[0]))[:-3],(str(rowmin[1]))[:4])
-# curs.execute("SELECT avg(temp) FROM temps WHERE timestamp>datetime('now','-%s hour') AND timestamp<=datetime('now')" % option)
- 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)
+ curs.execute("SELECT avg(value) FROM sensor_data WHERE timestamp>datetime('now','-%s hour') AND timestamp<=datetime('now','+2 hour')" % interval)
rowavg=curs.fetchone()
-
-
- print "
"
-
-
- print "Minumum temperature 
"
+ print "
Minumum temperature "
print rowstrmin
- print "Maximum temperature
"
+ print "Maximum temperature"
print rowstrmax
- print "Average temperature
"
+ print "Average temperature"
print "%.3f" % rowavg+"C"
-
print "
"
-
print "In the last hour:
"
print ""
- print "| Date/Time | Temperature |
"
+ print "| Date/Time | Temperature | Device | Sensor Name |
"
-# rows=curs.execute("SELECT * FROM temps WHERE timestamp>datetime('new','-1 hour') AND timestamp<=datetime('new')")
- 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')")
+
+ rows=curs.execute("SELECT timestamp,value,sensor_data.sensor_id,sensor_name FROM sensor_data,sensor WHERE timestamp>datetime('now','+1 hour') AND timestamp<=datetime('now','+2 hour') AND sensor_data.sensor_id = sensor.sensor_id")
for row in rows:
- rowstr="| {0} | {1}C |
".format(str(row[0]),str(row[1]))
+ rowstr="| {0} | {1}C | {2} | {3} |
".format((str(row[0]))[:-3],(str(row[1])[:4]),str(row[2]),str(row[3]))
print rowstr
print "
"
-
print "
"
-
conn.close()
-
-
-
def print_time_selector(option):
-
- print """"""
@@ -199,72 +180,50 @@ 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) <= 24:
+ if int(option_str) > 0 and int(option_str) <= 168:
return option_str
else:
return None
- else:
+ else:
return None
#return the option passed to the script
-def get_option():
+def getTimeInterval():
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()
+ interval=getTimeInterval()
+ if not interval:
+ interval= str(1) #24 hour std interval
- 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:
+ if getSensorCount() is 0:
print "No data found"
return
-
- # start printing the page
- print ""
+ else:
+ table = createMultiTable(interval)
# 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 ""
- print "Raspberry Pi Temperature Logger
"
+ print "Temperature Logger
"
print "
"
- print_time_selector(option)
+ print_time_selector(interval)
show_graph()
- show_stats(option)
+ show_stats(interval)
print ""
print ""
-
sys.stdout.flush()
if __name__=="__main__":
main()
-
-
-
-