aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatt Kohls <mattkohls13@gmail.com>2021-04-23 23:42:42 -0400
committerMatt Kohls <mattkohls13@gmail.com>2021-04-23 23:42:42 -0400
commit437c1179b545927197637c26bb2d87d20401e5f2 (patch)
tree590e57b5dd6f0d707d8e95a7a5242bd1e892053f
parent352c56375b4ec2af8f0b593b450069271bcd65e2 (diff)
downloadSensor-Server-437c1179b545927197637c26bb2d87d20401e5f2.tar.gz
Sensor-Server-437c1179b545927197637c26bb2d87d20401e5f2.tar.bz2
Sensor-Server-437c1179b545927197637c26bb2d87d20401e5f2.zip
Update based on what is used nowHEADmaster
Many changes, mostly to make landing page more readable Oh and a file to read a sensor attached via i2c on a Raspberry Pi and add that to the db
-rw-r--r--local.py84
-rwxr-xr-x[-rw-r--r--]sensor.py330
-rw-r--r--static/interactive.js64
-rw-r--r--static/pagedown.css155
-rw-r--r--templates/interactive.html39
-rw-r--r--templates/layout.html16
-rw-r--r--templates/show_entries.html43
7 files changed, 681 insertions, 50 deletions
diff --git a/local.py b/local.py
new file mode 100644
index 0000000..fb7803a
--- /dev/null
+++ b/local.py
@@ -0,0 +1,84 @@
+#!/usr/bin/env python3
+
+## Local Sensor Reading
+#
+# Reads data from sensor attached to Pi and saves in database
+#
+# Matt Kohls
+# 2021
+##
+
+import sqlite3
+from sqlite3 import Error
+from datetime import datetime
+import time
+import board
+import busio
+import adafruit_bme280
+
+
+# Local i2c BME sensor config
+i2c = busio.I2C(board.SCL, board.SDA)
+bme = adafruit_bme280.Adafruit_BME280_I2C(i2c)
+
+# Device ID for logging
+deviceId = 1
+
+# Start with connecting
+print("Connecting to db...")
+try:
+ db = sqlite3.connect('sensors.db')
+
+except Error:
+ print("DB connect fail: %s" % Error)
+ exit(-1)
+
+
+# Check if table exists, create if needed
+cursor = db.cursor()
+try:
+ cursor.execute('SELECT name from sqlite_master WHERE type = "table" AND name = "house"')
+ if cursor.fetchall() is []:
+ print("Empty db. Creating table...")
+ with open('house_schema.sql', 'r') as schemaFile:
+ schema = schemaFile.read()
+
+ cursor.executescript(schema)
+ db.commit()
+
+except Error:
+ print("DB cursor issues: %s" % Error)
+ exit(-1)
+
+# Main loop
+print("Logging...")
+while True:
+ now = datetime.now()
+ temp = bme.temperature
+ pressure = bme.pressure
+ humidity = bme.humidity
+ try:
+ cursor.execute('INSERT INTO house (date, temperature, humidity, pressure, deviceId) VALUES (?, ?, ?, ?, ?)',
+ [now, temp, humidity, pressure, deviceId])
+ db.commit()
+
+ except Error:
+ retryFail = False
+ for i in range(0, 5):
+ try:
+ cursor.execute('INSERT INTO house (date, temperature, humidity, pressure, deviceId) VALUES (?, ?, ?, ?, ?)',
+ [now, temp, humidity, pressure, deviceId])
+ db.commit()
+ retryFail = False
+ break
+
+ except Error:
+ retryFail = True
+
+ time.sleep(5)
+
+ if retryFail:
+ print("Unable to update db. Assuming the worst")
+ exit(-1)
+ time.sleep(300)
+
diff --git a/sensor.py b/sensor.py
index b21d51f..56c9594 100644..100755
--- a/sensor.py
+++ b/sensor.py
@@ -1,12 +1,19 @@
+#!/usr/bin/env python3
+
# imports
import sqlite3
-from flask import Flask, request, session, g, redirect, url_for, abort, render_template, flash
+from flask import Flask, request, session, g, redirect, url_for, abort, render_template, flash, json, Response
from contextlib import closing
-from datetime import datetime
-import pygal
+from datetime import datetime, timedelta
+from dateutil import parser
+
+
+from io import BytesIO
+from matplotlib.figure import Figure
+import matplotlib.dates as mdates
# configuration
-DATABASE = '/tmp/sensors.db'
+DATABASE = 'sensors.db'
DEBUG = True
SECRET_KEY = 'development_key'
@@ -19,14 +26,46 @@ app.config.from_object(__name__)
# initialize database
def init_db():
with closing(connect_db()) as db:
- with app.open_resource('schema.sql', mode='r') as f:
- db.cursor().executescript(f.read())
+ #with app.open_resource('schema.sql', mode='r') as f:
+ # db.cursor().executescript(f.read())
db.commit()
# connect to database
def connect_db():
return sqlite3.connect(app.config['DATABASE'])
+# pull data between two dates
+# startdate is for some date farther in the past than enddate
+def dates_between(startdate, enddate, table, deviceId):
+ if table is 'weather':
+ subset = g.db.execute('SELECT date, temperature, humidity, pressure FROM weather WHERE date BETWEEN ? AND ?', [startdate, enddate])
+ else:
+ subset = g.db.execute('SELECT date, temperature, humidity, pressure, battery FROM house WHERE (date BETWEEN ? AND ?) AND deviceId = ?', [startdate, enddate, deviceId])
+ return subset
+
+def getCurrent(requestArgs):
+ # the args should be formatted YYYYMMDDHHMMSS
+ start = requestArgs.get('start')
+ end = requestArgs.get('end')
+ table = requestArgs.get('type')
+ deviceId = request.args.get('deviceId')
+
+ # Sets default dates of information to be fetched, starttime will default to one day behind endtime, which defaults to now
+ if end is None:
+ endtime = datetime.now()
+ else:
+ endtime = datetime.strptime(end, "%Y%m%d%H%M%S")
+ if start is None:
+ starttime = endtime - timedelta(days=1)
+ else:
+ starttime = datetime.strptime(start, "%Y%m%d%H%M%S")
+ if table is None:
+ table = 'house'
+ if deviceId is None:
+ deviceId = 1
+
+ return dates_between(starttime, endtime, table, deviceId)
+
# handle requests
@app.before_request
def before_request():
@@ -41,47 +80,238 @@ def teardown_request(exception):
# viewing database
@app.route('/')
def show_entries():
- cur = g.db.execute('SELECT date, temperature, humidity, pressure FROM weather ORDER BY id desc')
+ enddate = datetime.now()
+ startdate = enddate - timedelta(days=1)
+ deviceId = 1
+ cur = g.db.execute('SELECT date, temperature, humidity, pressure FROM house WHERE (date BETWEEN ? AND ?) AND deviceId = ? ORDER BY id desc ', [startdate, enddate, deviceId])
entries = [dict(date=row[0], temperature=row[1], humidity=row[2], pressure=row[3]) for row in cur.fetchall()]
+ temp = "{:.1f}".format(entries[0].get("temperature") * 1.8 + 32)
+ humid = "{:.1f}".format(entries[0].get("humidity"))
+ current = dict(temperature=temp, humidity=humid)
+
+ return render_template('show_entries.html', log=entries, current=current, devId=1)
- return render_template('show_entries.html', weather=entries)
+@app.route('/bedroom')
+def bedroom_entries():
+ enddate = datetime.now()
+ startdate = enddate - timedelta(days=1)
+ deviceId = 1
+ cur = g.db.execute('SELECT date, temperature, humidity, pressure FROM house WHERE (date BETWEEN ? AND ?) AND deviceId = ? ORDER BY id desc ', [startdate, enddate, deviceId])
+ entries = [dict(date=row[0], temperature=row[1], humidity=row[2], pressure=row[3]) for row in cur.fetchall()]
+ temp = "{:.1f}".format(entries[0].get("temperature") * 1.8 + 32)
+ humid = "{:.1f}".format(entries[0].get("humidity"))
+ current = dict(temperature=temp, humidity=humid)
+
+ return render_template('show_entries.html', log=entries, current=current, devId=1)
+
+@app.route('/mainfloor')
+def mainfloor_entries():
+ enddate = datetime.now()
+ startdate = enddate - timedelta(days=1)
+ deviceId = 2
+ cur = g.db.execute('SELECT date, temperature, humidity, pressure FROM house WHERE (date BETWEEN ? AND ?) AND deviceId = ? ORDER BY id desc ', [startdate, enddate, deviceId])
+ entries = [dict(date=row[0], temperature=row[1], humidity=row[2], pressure=row[3]) for row in cur.fetchall()]
+ temp = "{:.1f}".format(entries[0].get("temperature") * 1.8 + 32)
+ humid = "{:.1f}".format(entries[0].get("humidity"))
+ current = dict(temperature=temp, humidity=humid)
+
+ return render_template('show_entries.html', log=entries, current=current, devId=2)
+
+@app.route('/interactive')
+def interactive():
+ return render_template('interactive.html')
# drawing graphs
-@app.route('/tgraph.svg')
+@app.route('/tgraph.png', methods=['GET'])
def draw_t_graph():
- cur = g.db.execute('SELECT date, temperature, humidity, pressure FROM weather ORDER BY id desc')
+ cur = getCurrent(request.args)
+ data = cur.fetchall()
+ dates = []
+ tempsC = []
+ tempsF = []
- datetimeline = pygal.DateTimeLine(
- x_label_rotation=30, truncate_label=-1,
- x_value_formatter=lambda dt: dt.strftime('%d, %b %Y %I:%M %p')
- )
- datetimeline.add("Temp", [(datetime.strptime(row[0], '%Y-%m-%d %H:%M:%S.%f'), float(row[1])) for row in cur.fetchall()])
+ for row in data:
+ dates.append(parser.parse(row[0]))
+ tempsC.append(row[1])
+ tempsF.append(row[1] * 1.8 + 32)
- return datetimeline.render_response()
+ # Generate the figure **without using pyplot**.
+ fig = Figure()
+ ax = fig.subplots()
+ bx = ax.twinx()
+ locator = mdates.AutoDateLocator(minticks=3, maxticks=7)
+ formatter = mdates.ConciseDateFormatter(locator)
+ ax.xaxis.set_major_locator(locator)
+ ax.xaxis.set_major_formatter(formatter)
+ bx.xaxis.set_major_locator(locator)
+ bx.xaxis.set_major_formatter(formatter)
+ ax.plot(dates, tempsC, color="C1")
+ ax.set_xlabel("Timestamps")
+ ax.set_ylabel("Celsius")
+ ax.set_title("Temperature")
+ bx.plot(dates, tempsF, visible=False)
+ bx.set_ylabel("Fahrenheit")
+ # Save it to a temporary buffer.
+ buf = BytesIO()
+ fig.savefig(buf, format="png")
-@app.route('/hgraph.svg')
+ return Response(buf.getvalue(), mimetype='image/png')
+
+@app.route('/hgraph.png', methods=['GET'])
def draw_h_graph():
- cur = g.db.execute('SELECT date, temperature, humidity, pressure FROM weather ORDER BY id desc')
+ data = getCurrent(request.args)
+ dates = []
+ humidities = []
+
+ for row in data:
+ dates.append(parser.parse(row[0]))
+ humidities.append(row[2])
+
+ # Generate the figure **without using pyplot**.
+ fig = Figure()
+ ax = fig.subplots()
+ locator = mdates.AutoDateLocator(minticks=3, maxticks=7)
+ formatter = mdates.ConciseDateFormatter(locator)
+ ax.xaxis.set_major_locator(locator)
+ ax.xaxis.set_major_formatter(formatter)
+ ax.plot(dates, humidities, color="C0")
+ ax.set_xlabel("Timestamps")
+ ax.set_ylabel("Percent")
+ ax.set_title("Relative Humidity")
+ # Save it to a temporary buffer.
+ buf = BytesIO()
+ fig.savefig(buf, format="png")
+
+ return Response(buf.getvalue(), mimetype='image/png')
+
+@app.route('/htgraph.png', methods=['GET'])
+def draw_ht_graph():
+ cur = getCurrent(request.args)
+ data = cur.fetchall()
+ dates = []
+ humidities = []
+ #tempsC = []
+ tempsF = []
+
+ for row in data:
+ dates.append(parser.parse(row[0]))
+ # tempsC.append(row[1])
+ tempsF.append(row[1] * 1.8 + 32)
+ humidities.append(row[2])
+
+ fig = Figure()
+ #fig.subplots_adjust(right=0.75)
+ ax = fig.subplots()
+ bx = ax.twinx()
+ #cx = ax.twinx()
- datetimeline = pygal.DateTimeLine(
- x_label_rotation=30, truncate_label=-1,
- x_value_formatter=lambda dt: dt.strftime('%d, %b %Y %I:%M %p')
- )
- datetimeline.add("Humidity", [(datetime.strptime(row[0], '%Y-%m-%d %H:%M:%S.%f'), float(row[2])) for row in cur.fetchall()])
+ #cx.spines["right"].set_position(("axes", 1.2))
+ #cx.set_frame_on(True)
+ #cx.patch.set_visible(False)
+ #for sp in cx.spines.values():
+ # sp.set_visible(False)
+ #cx.spines["right"].set_visible(True)
- return datetimeline.render_response()
+ locator = mdates.AutoDateLocator(minticks=3, maxticks=7)
+ formatter = mdates.ConciseDateFormatter(locator)
+ ax.xaxis.set_major_locator(locator)
+ ax.xaxis.set_major_formatter(formatter)
+ bx.xaxis.set_major_locator(locator)
+ bx.xaxis.set_major_formatter(formatter)
+ #cx.xaxis.set_major_locator(locator)
+ #cx.xaxis.set_major_formatter(formatter)
-@app.route('/pgraph.svg')
+ hline, = ax.plot(dates, humidities, color="C0", label="Relative Humidity")
+ ax.set_xlabel("Timestamps")
+ ax.set_ylabel("Percent")
+ ax.set_title("Humidity and Temperature")
+ tline, = bx.plot(dates, tempsF, color="C1", label="Temperature")
+ bx.set_ylabel("Fahrenheit")
+ #cx.plot(dates, tempsC, visible=False)
+ #cx.set_ylabel("Celsius")
+
+ lines = [hline, tline]
+ ax.legend(lines, [l.get_label() for l in lines])
+
+ buf = BytesIO()
+ fig.savefig(buf, format="png")
+
+ return Response(buf.getvalue(), mimetype='image/png')
+
+@app.route('/pgraph.png', methods=['GET'])
def draw_p_graph():
- cur = g.db.execute('SELECT date, temperature, humidity, pressure FROM weather ORDER BY id desc')
+ data = getCurrent(request.args)
+ dates = []
+ pressures = []
+
+ for row in data:
+ dates.append(parser.parse(row[0]))
+ pressures.append(row[3])
+
+ # Generate the figure **without using pyplot**.
+ fig = Figure()
+ ax = fig.subplots()
+ locator = mdates.AutoDateLocator(minticks=3, maxticks=7)
+ formatter = mdates.ConciseDateFormatter(locator)
+ ax.xaxis.set_major_locator(locator)
+ ax.xaxis.set_major_formatter(formatter)
+ ax.plot(dates, pressures, color="C2")
+ ax.set_xlabel("Timestamps")
+ ax.set_ylabel("hPa")
+ ax.set_title("Pressure")
+ # Save it to a temporary buffer.
+ buf = BytesIO()
+ fig.savefig(buf, format="png")
+
+ return Response(buf.getvalue(), mimetype='image/png')
+
+@app.route('/bgraph.png', methods=['GET'])
+def draw_b_graph():
+ data = getCurrent(request.args)
+ dates = []
+ batteries = []
+
+ for row in data:
+ dates.append(parser.parse(row[0]))
+ batteries.append(row[4])
+
+ # Generate the figure **without using pyplot**.
+ fig = Figure()
+ ax = fig.subplots()
+ locator = mdates.AutoDateLocator(minticks=3, maxticks=7)
+ formatter = mdates.ConciseDateFormatter(locator)
+ ax.xaxis.set_major_locator(locator)
+ ax.xaxis.set_major_formatter(formatter)
+ ax.plot(dates, batteries, color="C3")
+ ax.set_xlabel("Timestamps")
+ ax.set_ylabel("Volts")
+ ax.set_title("Battery Voltage")
+ # Save it to a temporary buffer.
+ buf = BytesIO()
+ fig.savefig(buf, format="png")
- datetimeline = pygal.DateTimeLine(
- x_label_rotation=30, truncate_label=-1,
- x_value_formatter=lambda dt: dt.strftime('%d, %b %Y %I:%M %p')
- )
- datetimeline.add("Pressure", [(datetime.strptime(row[0], '%Y-%m-%d %H:%M:%S.%f'), float(row[3])) for row in cur.fetchall()])
+ return Response(buf.getvalue(), mimetype='image/png')
- return datetimeline.render_response()
+## Database Retrieval Route
+#
+# Sends the information in the database in JSON format
+@app.route('/get_database')
+def get_database():
+ entries = getCurrent(request.args)
+ empList = []
+ for emp in entries:
+ empDict = {
+ 'date': emp[0],
+ 'temperature': emp[1],
+ 'humidity': emp[2],
+ 'pressure': emp[3] }
+ empList.append(empDict)
+ response = app.response_class(
+ response=json.dumps(empList),
+ status=200,
+ mimetype='application/json'
+ )
+ return response
# adding entries to database
@@ -100,5 +330,39 @@ def add_data():
return render_template('show_entries.html'), 200
+@app.route('/json_data', methods=['POST'])
+def add_json_data():
+ mkey = request.args.get('key')
+ if mkey != SECRET_KEY:
+ abort(401)
+
+ # Validate the request body contains JSON
+ if request.is_json:
+ # Parse the JSON into a Python dictionary
+ req = request.get_json()
+
+ # Print the dictionary
+ print(req)
+
+ try:
+ temp = req['temperature']
+ humidity = req['humidity']
+ pressure = req['pressure']
+ battery = req['battery']
+ deviceId = req['deviceId']
+ now = datetime.now()
+ g.db.execute('INSERT INTO house (date, temperature, humidity, pressure, deviceId, battery) VALUES (?, ?, ?, ?, ?, ?)', [now, temp, humidity, pressure, deviceId, battery])
+ g.db.commit()
+ except:
+ print("bad json")
+
+ # Return a string along with an HTTP status code
+ return "JSON received!", 200
+
+ else:
+ # The request body wasn't JSON so return a 400 HTTP status code
+ return "Request was not JSON", 400
+
+
if __name__ == '__main__':
- app.run()
+ app.run(host='0.0.0.0')
diff --git a/static/interactive.js b/static/interactive.js
new file mode 100644
index 0000000..de44670
--- /dev/null
+++ b/static/interactive.js
@@ -0,0 +1,64 @@
+/**
+ * Script to change the shown graph
+ *
+ * Matt Kohls
+ * 2021
+ */
+
+const form = document.getElementById('query');
+const submitButton = document.getElementById('submit');
+const figure = document.getElementById('figure');
+
+function sendRequest(data) {
+ let url = "/",
+ urlEncoded = "",
+ urlEncodedPairs = [],
+ name,
+ startDate,
+ startTime,
+ endDate,
+ endTime;
+
+ for (name of data) {
+ switch (name[0]) {
+ case 'graph':
+ url = url.concat(name[1]);
+ break;
+ case 'sd':
+ startDate = name[1].replace(/-/g, '');
+ break;
+ case 'st':
+ startTime = name[1].replace(/:/g, '').concat('00');
+ case 'ed':
+ endDate = name[1].replace(/-/g, '');
+ break;
+ case 'et':
+ endTime = name[1].replace(/:/g, '').concat('00');
+ break;
+ case 'deviceId':
+ default:
+ urlEncodedPairs.push(name[0] + '=' + name[1]);
+ }
+ }
+ if (startDate !== "") {
+ if (startTime === "00") {
+ startTime = "000000";
+ }
+ urlEncodedPairs.push('start=' + startDate + startTime);
+ }
+ if (endDate !== "") {
+ if (endTime === "00") {
+ endTime = "000000";
+ }
+ urlEncodedPairs.push('end=' + endDate + endTime);
+ }
+
+ urlEncoded = urlEncodedPairs.join('&');
+ figure.setAttribute('src', url + '?' + urlEncoded);
+}
+
+submitButton.addEventListener('click', function() {
+ const formData = new FormData(form);
+ sendRequest(formData);
+})
+
diff --git a/static/pagedown.css b/static/pagedown.css
new file mode 100644
index 0000000..7f9c3e0
--- /dev/null
+++ b/static/pagedown.css
@@ -0,0 +1,155 @@
+@font-face {
+ font-family: "Courier 10 Pitch";
+ src: url(/fonts/courier10bt-regular.woff);
+ font-weight: normal;
+ font-style: normal;
+}
+
+@font-face {
+ font-family: "Courier 10 Pitch";
+ src: url(/fonts/courier10bt-bold.woff);
+ font-weight: bold;
+ font-style: normal;
+}
+
+@font-face {
+ font-family: "Courier 10 Pitch";
+ src: url(/fonts/courier10bt-italic.woff);
+ font-weight: normal;
+ font-style: italic;
+}
+
+@font-face {
+ font-family: "Courier 10 Pitch";
+ src: url(/fonts/courier10bt-bolditalic.woff);
+ font-weight: bold;
+ font-style: italic;
+}
+
+@font-face {
+ font-family: Literata;
+ src: url(/fonts/Literata-Regular.woff)
+ font-weight: normal;
+ font-style: normal;
+}
+
+@font-face {
+ font-family: Literata;
+ src: url(/fonts/Literata-Bold.woff)
+ font-weight: bold;
+ font-style: normal;
+}
+
+@font-face {
+ font-family: Literata;
+ src: url(/fonts/Literata-Italic.woff)
+ font-weight: normal;
+ font-style: italic;
+}
+
+@font-face {
+ font-family: Literata;
+ src: url(/fonts/Literata-BoldItalic.woff)
+ font-weight: bold;
+ font-style: italic;
+}
+
+html, body {
+ min-height: 100%;
+ height: 100%;
+ margin: 1em
+}
+
+body {
+ color: #212529;
+ background-color: #fff;
+ font-family: "Nimbus Sans L", Helvetica, sans-serif;
+}
+
+img, video {
+ display: block;
+ max-width: 80%;
+ box-shadow: 1px 1px 5px 0 rgba(0,0,0,.4);
+ margin: 0 auto
+}
+
+figcaption {
+ text-align: center;
+ margin: 0 auto
+}
+
+pre {
+ font-family: "Courier 10 Pitch", Courier, monospace;
+ background: #eee;
+ padding: .5rem;
+ margin: 0 -.5rem;
+ overflow-x: auto
+}
+
+nav {
+ margin: 0 auto;
+ clear: both
+}
+
+nav a:not(:first-child) {
+ margin-left: 1rem
+}
+
+nav .brand {
+ font-size: 1.25rem;
+ position: relative;
+ top: 1px
+}
+
+label {
+ display: inline-block;
+ margin-bottom: .25rem
+}
+
+aside {
+ border-left-style: dotted;
+ padding: 1em
+}
+
+h1 {
+ font-family: Literata, serif;
+}
+
+h2 {
+ font-family: Literata, serif;
+}
+
+h3 {
+ font-family: Literata, serif;
+}
+
+h4 {
+ font-family: Literata, serif;
+}
+
+header {
+ width: 50%;
+ margin-top: .5rem;
+}
+
+table {
+ border-collapse: collapse;
+ border: 0px
+}
+
+th {
+ border-bottom: 1px solid #212121
+}
+
+th, td {
+ padding: 5px;
+}
+
+tr:nth-child(even) {
+ background-color: #f6f6f6
+}
+
+footer {
+ width: 50%;
+ margin: 0 0 1rem
+}
diff --git a/templates/interactive.html b/templates/interactive.html
new file mode 100644
index 0000000..1756865
--- /dev/null
+++ b/templates/interactive.html
@@ -0,0 +1,39 @@
+{% extends "layout.html" %}
+{% block body %}
+ <form id="query">
+ <p>
+ <label>Location</label>
+ <select id="deviceId" name="deviceId">
+ <option value="1">Bedroom</option>
+ <option value="2">Mainfloor</option>
+ </select>
+ </p>
+ <p>
+ <label>Graph Type</label>
+ <select id="graph" name="graph">
+ <option value="htgraph.png">Humidity &amp; Temperature</option>
+ <option value="tgraph.png">Temperature</option>
+ <option value="hgraph.png">Humidity</option>
+ <option value="pgraph.png">Pressure</option>
+ <option value="bgraph.png">Battery</option>
+ </select>
+ </p>
+ <p>
+ <label>Start Date</label>
+ <input type="date" name="sd" id="sd">
+ <input type="time" name="st" id="st">
+ </p>
+ <p>
+ <label>End Date</label>
+ <input type="date" name="ed" id="ed">
+ <input type="time" name="et" id="et">
+ </p>
+ </form>
+ <button id='submit'>Submit</button>
+
+ <figure>
+ <embed id="figure" type="image/png" src="/htgraph.png?deviceId=2" />
+ </figure>
+
+ <script src="static/interactive.js"></script>
+{% endblock %}
diff --git a/templates/layout.html b/templates/layout.html
index 2a06690..a49f142 100644
--- a/templates/layout.html
+++ b/templates/layout.html
@@ -1,12 +1,12 @@
<!doctype html>
-<title>Weather</title>
-<link rel=stylesheet type=text/css href="{{ url_for('static', filename='style.css') }}">
+<title>Sensor</title>
+<link rel=stylesheet type=text/css href="{{ url_for('static', filename='pagedown.css') }}">
<div class=page>
- <h1>Weather</h1>
- <div class=metanav>
- </div>
- {% for message in get_flashed_messages() %}
- <div class=flash>{{ message }}</div>
- {% endfor %}
+ <h1>Sensor Readings</h1>
+ <hr>
+ <a href="bedroom">Bedroom</a> <a href="mainfloor">Mainfloor</a> <a href="interactive">Interactive</a>
+ <hr>
+ <main>
{% block body %}{% endblock %}
+ </main>
</div>
diff --git a/templates/show_entries.html b/templates/show_entries.html
index 572f360..86451df 100644
--- a/templates/show_entries.html
+++ b/templates/show_entries.html
@@ -1,19 +1,44 @@
{% extends "layout.html" %}
{% block body %}
+ <aside>
+ <b>{% if devId == 1 %}Bedroom
+ {% else %}Mainfloor
+ {% endif %}Currently:</b>
+ <ul class=current>
+ <li>{{ current.temperature }}&#176;F</li>
+ <li>{{ current.humidity }}% humidity</li>
+ </ul>
+ </aside>
<figure>
- <embed type="image/svg+xml" src="/tgraph.svg" />
+ <embed type="image/png" src="/htgraph.png?deviceId={{ devId }}" />
</figure>
<figure>
- <embed type="image/svg+xml" src="/hgraph.svg" />
+ <embed type="image/png" src="/pgraph.png?deviceId={{ devId }}" />
</figure>
+ {% if devId == 2 %}
<figure>
- <embed type="image/svg+xml" src="/pgraph.svg" />
+ <embed type="image/png" src="/bgraph.png?deviceId={{ devId }}" />
</figure>
- <ul class=weather>
- {% for entry in weather %}
- <li><h2>{{ entry.date }}</h2>Temp: {{ entry.temperature }}, Humidity: {{ entry.humidity }}, Pressure: {{ entry.pressure }}
- {% else %}
- <li><em>No entries here so far</em>
+ {% endif %}
+
+ <hr>
+ <h2>Readings from the past 24 hours</h2>
+ <p>
+ <table class=log>
+ <tr>
+ <th>Timestamp</th>
+ <th>Temperature (C)</th>
+ <th>Humidity (%)</th>
+ <th>Pressure (hPa)</th>
+ </tr>
+ {% for entry in log %}
+ <tr>
+ <td>{{ entry.date }}</td>
+ <td>{{ entry.temperature }}</td>
+ <td>{{ entry.humidity }}</td>
+ <td>{{ entry.pressure }}</td>
+ </tr>
{% endfor %}
- </ul>
+ </table>
+ </p>
{% endblock %}