diff options
| author | Matt Kohls <mattkohls13@gmail.com> | 2021-04-23 23:42:42 -0400 | 
|---|---|---|
| committer | Matt Kohls <mattkohls13@gmail.com> | 2021-04-23 23:42:42 -0400 | 
| commit | 437c1179b545927197637c26bb2d87d20401e5f2 (patch) | |
| tree | 590e57b5dd6f0d707d8e95a7a5242bd1e892053f | |
| parent | 352c56375b4ec2af8f0b593b450069271bcd65e2 (diff) | |
| download | Sensor-Server-437c1179b545927197637c26bb2d87d20401e5f2.tar.gz Sensor-Server-437c1179b545927197637c26bb2d87d20401e5f2.tar.bz2 Sensor-Server-437c1179b545927197637c26bb2d87d20401e5f2.zip  | |
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.py | 84 | ||||
| -rwxr-xr-x[-rw-r--r--] | sensor.py | 330 | ||||
| -rw-r--r-- | static/interactive.js | 64 | ||||
| -rw-r--r-- | static/pagedown.css | 155 | ||||
| -rw-r--r-- | templates/interactive.html | 39 | ||||
| -rw-r--r-- | templates/layout.html | 16 | ||||
| -rw-r--r-- | templates/show_entries.html | 43 | 
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 & 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 }}°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 %}  | 
